aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/afp/fonts
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/afp/fonts')
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java157
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFont.java113
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java106
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontCollection.java92
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontInfo.java63
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontReader.java592
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPPageFonts.java64
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSet.java318
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java275
-rw-r--r--src/java/org/apache/fop/afp/fonts/FontRuntimeException.java48
-rw-r--r--src/java/org/apache/fop/afp/fonts/FopCharacterSet.java137
-rw-r--r--src/java/org/apache/fop/afp/fonts/OutlineFont.java182
-rw-r--r--src/java/org/apache/fop/afp/fonts/RasterFont.java238
-rw-r--r--src/java/org/apache/fop/afp/fonts/package.html23
14 files changed, 2408 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
new file mode 100644
index 000000000..e607bef5f
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
@@ -0,0 +1,157 @@
+/*
+ * 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;
+
+import org.apache.fop.fonts.Base14Font;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontCollection;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.base14.Courier;
+import org.apache.fop.fonts.base14.CourierBold;
+import org.apache.fop.fonts.base14.CourierBoldOblique;
+import org.apache.fop.fonts.base14.CourierOblique;
+import org.apache.fop.fonts.base14.Helvetica;
+import org.apache.fop.fonts.base14.HelveticaBold;
+import org.apache.fop.fonts.base14.HelveticaOblique;
+import org.apache.fop.fonts.base14.TimesBold;
+import org.apache.fop.fonts.base14.TimesBoldItalic;
+import org.apache.fop.fonts.base14.TimesItalic;
+import org.apache.fop.fonts.base14.TimesRoman;
+
+/**
+ * Sets up a typical Base 12 font configuration for AFP
+ */
+public class AFPBase12FontCollection implements FontCollection {
+
+ /** standard raster font sizes */
+ private static final int[] RASTER_SIZES = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 30, 36};
+
+ /** standard raster font charset references */
+ private static final String[] CHARSET_REF = {
+ "60", "70", "80", "90", "00", "A0", "B0", "D0", "F0", "H0", "J0", "N0", "T0", "Z0"};
+
+ private void addCharacterSet(RasterFont font, String charsetName, Base14Font base14) {
+ for (int i = 0; i < RASTER_SIZES.length; i++) {
+ int size = RASTER_SIZES[i];
+ FopCharacterSet characterSet = new FopCharacterSet(
+ CharacterSet.DEFAULT_CODEPAGE, CharacterSet.DEFAULT_ENCODING,
+ charsetName + CHARSET_REF[i], base14);
+ font.addCharacterSet(size, characterSet);
+ }
+ }
+
+ private int addFontProperties(FontInfo fontInfo, AFPFont font,
+ String[] names, String style, int weight, int num) {
+ String internalFontKey = "F" + num;
+ fontInfo.addMetrics(internalFontKey, font);
+ fontInfo.addFontProperties(internalFontKey, names, style, weight);
+ num++;
+ return num;
+ }
+
+ /** {@inheritDoc} */
+ public int setup(int start, FontInfo fontInfo) {
+
+ /**
+ * Add the base 12 fonts (Helvetica, Times and Courier)
+ *
+ * Note: this default font configuration may not be available
+ * on your AFP environment.
+ */
+ int num = start;
+ RasterFont font = null;
+
+ /** standard font family reference names for Helvetica font */
+ final String[] helveticaNames = {"Helvetica", "Arial", "sans-serif"};
+ font = new RasterFont("Helvetica");
+ addCharacterSet(font, "C0H200", new Helvetica());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Helvetica Italic");
+ addCharacterSet(font, "C0H300", new HelveticaOblique());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Helvetica (Semi) Bold");
+ addCharacterSet(font, "C0H400", new HelveticaBold());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
+
+ font = new RasterFont("Helvetica Italic (Semi) Bold");
+ addCharacterSet(font, "C0H500", new HelveticaOblique());
+ num = addFontProperties(fontInfo, font, helveticaNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
+
+
+ /** standard font family reference names for Times font */
+
+ /** any is treated as serif */
+ final String[] timesNames = {"Times", "TimesRoman", "Times Roman", "Times-Roman",
+ "Times New Roman", "TimesNewRoman", "serif", "any"};
+
+ font = new RasterFont("Times Roman");
+ addCharacterSet(font, "CON200", new TimesRoman());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Times Roman Italic");
+ addCharacterSet(font, "CON300", new TimesItalic());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Times Roman Bold");
+ addCharacterSet(font, "CON400", new TimesBold());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
+
+ font = new RasterFont("Times Roman Italic Bold");
+ addCharacterSet(font, "CON500", new TimesBoldItalic());
+ num = addFontProperties(fontInfo, font, timesNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
+
+
+ /** standard font family reference names for Courier font */
+ final String[] courierNames = {"Courier", "monospace"};
+
+ font = new RasterFont("Courier");
+ addCharacterSet(font, "C04200", new Courier());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Courier Italic");
+ addCharacterSet(font, "C04300", new CourierOblique());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
+
+ font = new RasterFont("Courier Bold");
+ addCharacterSet(font, "C04400", new CourierBold());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
+
+ font = new RasterFont("Courier Italic Bold");
+ addCharacterSet(font, "C04500", new CourierBoldOblique());
+ num = addFontProperties(fontInfo, font, courierNames,
+ Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
+
+ return num;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFont.java b/src/java/org/apache/fop/afp/fonts/AFPFont.java
new file mode 100644
index 000000000..dc8f9c315
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPFont.java
@@ -0,0 +1,113 @@
+/*
+ * 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;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.Typeface;
+
+
+/**
+ * All implementations of AFP fonts should extend this base class,
+ * the object implements the FontMetrics information.
+ * <p/>
+ */
+public abstract class AFPFont extends Typeface {
+
+ /** The font name */
+ protected String name;
+
+ /**
+ * Constructor for the base font requires the name.
+ * @param name the name of the font
+ */
+ public AFPFont(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ public String getFontName() {
+ return this.name;
+ }
+
+ /** {@inheritDoc} */
+ public String getEmbedFontName() {
+ return this.name;
+ }
+
+ /** {@inheritDoc} */
+ public String getFullName() {
+ return getFontName();
+ }
+
+ /** {@inheritDoc} */
+ public Set getFamilyNames() {
+ Set s = new java.util.HashSet();
+ s.add(this.name);
+ return s;
+ }
+
+ /**
+ * Returns the type of the font.
+ * @return the font type
+ */
+ public FontType getFontType() {
+ return FontType.OTHER;
+ }
+
+ /**
+ * Indicates if the font has kerning information.
+ * @return True, if kerning is available.
+ */
+ public boolean hasKerningInfo() {
+ return false;
+ }
+
+ /**
+ * Returns the kerning map for the font.
+ * @return the kerning map
+ */
+ public Map getKerningInfo() {
+ return null;
+ }
+
+ /**
+ * Returns the character set for a given size
+ * @param size the font size
+ * @return the character set object
+ */
+ public abstract CharacterSet getCharacterSet(int size);
+
+ /**
+ * Determines whether this font contains a particular character/glyph.
+ * @param c character to check
+ * @return True if the character is supported, False otherwise
+ */
+ public boolean hasChar(char c) {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "name=" + name;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java
new file mode 100644
index 000000000..de7f7f5be
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java
@@ -0,0 +1,106 @@
+/*
+ * 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;
+
+/**
+ * This class encapsulates the font attributes that need to be included
+ * in the AFP data stream. This class does not assist in converting the
+ * font attributes to AFP code pages and character set values.
+ */
+public class AFPFontAttributes {
+
+ /** the font reference */
+ private int fontReference;
+
+ /** the font key */
+ private final String fontKey;
+
+ /** the font */
+ private final AFPFont font;
+
+ /** the point size */
+ private final int pointSize;
+
+ /**
+ * Constructor for the AFPFontAttributes
+ *
+ * @param fontKey the font key
+ * @param font the font
+ * @param pointSize the point size
+ */
+ public AFPFontAttributes(String fontKey, AFPFont font, int pointSize) {
+ this.fontKey = fontKey;
+ this.font = font;
+ this.pointSize = pointSize;
+ }
+
+ /**
+ * Return the font
+ *
+ * @return the font
+ */
+ public AFPFont getFont() {
+ return font;
+ }
+
+ /**
+ * Return the FontKey attribute
+ *
+ * @return the FontKey attribute
+ */
+ public String getFontKey() {
+ return fontKey + pointSize;
+ }
+
+ /**
+ * Return the point size attribute
+ *
+ * @return the point size attribute
+ */
+ public int getPointSize() {
+ return pointSize;
+ }
+
+ /**
+ * Return the FontReference attribute
+ *
+ * @return the FontReference attribute
+ */
+ public int getFontReference() {
+ return fontReference;
+ }
+
+ /**
+ * Sets the FontReference attribute
+ *
+ * @param fontReference the FontReference to set
+ */
+ public void setFontReference(int fontReference) {
+ this.fontReference = fontReference;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "fontReference=" + fontReference
+ + ", fontKey=" + fontKey
+ + ", font=" + font
+ + ", pointSize=" + pointSize;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
new file mode 100644
index 000000000..670373fbf
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.afp.AFPEventProducer;
+import org.apache.fop.events.EventBroadcaster;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontCollection;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+/**
+ * A base collection of AFP fonts
+ */
+public class AFPFontCollection implements FontCollection {
+
+ private final EventBroadcaster eventBroadcaster;
+
+ private final List/*<AFPFontInfo>*/ fontInfoList;
+
+ /**
+ * Main constructor
+ *
+ * @param eventBroadcaster the event broadcaster
+ * @param fontInfoList the font info list
+ */
+ public AFPFontCollection(EventBroadcaster eventBroadcaster,
+ List/*<AFPFontInfo>*/ fontInfoList) {
+ this.eventBroadcaster = eventBroadcaster;
+ this.fontInfoList = fontInfoList;
+ }
+
+ /** {@inheritDoc} */
+ public int setup(int start, FontInfo fontInfo) {
+ int num = 1;
+ AFPEventProducer eventProducer = AFPEventProducer.Provider.get(eventBroadcaster);
+ if (fontInfoList != null && fontInfoList.size() > 0) {
+ for (Iterator it = fontInfoList.iterator(); it.hasNext();) {
+ AFPFontInfo afpFontInfo = (AFPFontInfo)it.next();
+ AFPFont afpFont = afpFontInfo.getAFPFont();
+ List/*<FontTriplet>*/ tripletList = afpFontInfo.getFontTriplets();
+ for (Iterator it2 = tripletList.iterator(); it2.hasNext();) {
+ FontTriplet triplet = (FontTriplet)it2.next();
+ fontInfo.addFontProperties("F" + num,
+ triplet.getName(), triplet.getStyle(), triplet.getWeight());
+ fontInfo.addMetrics("F" + num, afpFont);
+ num++;
+ }
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
+ }
+ if (!fontInfo.hasFont("any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD)) {
+ eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
+ }
+ } else {
+ eventProducer.warnDefaultFontSetup(this);
+
+ // Go with a default base 12 configuration for AFP environments
+ FontCollection base12FontCollection = new AFPBase12FontCollection();
+ num = base12FontCollection.setup(num, fontInfo);
+ }
+ return num;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java b/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java
new file mode 100644
index 000000000..0259435c6
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import java.util.List;
+
+
+/**
+ * FontInfo contains meta information on fonts
+ */
+public class AFPFontInfo {
+
+ private AFPFont font;
+ private List/*<FontTriplet>*/ tripletList;
+
+ /**
+ * Main constructor
+ *
+ * @param afpFont The AFP Font
+ * @param tripletList List of font triplets to associate with this font
+ */
+ public AFPFontInfo(AFPFont afpFont, List/*<FontTriplet>*/ tripletList) {
+ this.font = afpFont;
+ this.tripletList = tripletList;
+ }
+
+ /**
+ * Returns the afp font
+ *
+ * @return the afp font
+ */
+ public AFPFont getAFPFont() {
+ return font;
+ }
+
+ /**
+ * Returns the list of font triplets associated with this font.
+ *
+ * @return List of font triplets
+ */
+ public List/*<FontTriplet>*/ getFontTriplets() {
+ return tripletList;
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
new file mode 100644
index 000000000..16c341ac4
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java
@@ -0,0 +1,592 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.StructuredFieldReader;
+
+/**
+ * The AFPFontReader is responsible for reading the font attributes from binary
+ * code page files and the character set metric files. In IBM font structure, a
+ * code page maps each character of text to the characters in a character set.
+ * Each character is translated into a code point. When the character is
+ * printed, each code point is matched to a character ID on the code page
+ * specified. The character ID is then matched to the image (raster pattern or
+ * outline pattern) of the character in the character set specified. The image
+ * in the character set is the image that is printed in the document. To be a
+ * valid code page for a particular character set, all character IDs in the code
+ * page must be included in that character set. <p/>This class will read the
+ * font information from the binary code page files and character set metric
+ * files in order to determine the correct metrics to use when rendering the
+ * formatted object. <p/>
+ *
+ * @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a>
+ */
+public final class AFPFontReader {
+
+ /**
+ * Static logging instance
+ */
+ protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.fonts");
+
+ /**
+ * Template used to convert lists to arrays.
+ */
+ private static final CharacterSetOrientation[] EMPTY_CSO_ARRAY = new CharacterSetOrientation[0];
+
+ /** Codepage MO:DCA structured field. */
+ private static final byte[] CODEPAGE_SF = new byte[] {
+ (byte) 0xD3, (byte) 0xA8, (byte) 0x87};
+
+ /** Character table MO:DCA structured field. */
+ private static final byte[] CHARACTER_TABLE_SF = new byte[] {
+ (byte) 0xD3, (byte) 0x8C, (byte) 0x87};
+
+ /** Font control MO:DCA structured field. */
+ private static final byte[] FONT_CONTROL_SF = new byte[] {
+ (byte) 0xD3, (byte) 0xA7, (byte) 0x89 };
+
+ /** Font orientation MO:DCA structured field. */
+ private static final byte[] FONT_ORIENTATION_SF = new byte[] {
+ (byte) 0xD3, (byte) 0xAE, (byte) 0x89 };
+
+ /** Font position MO:DCA structured field. */
+ private static final byte[] FONT_POSITION_SF = new byte[] {
+ (byte) 0xD3, (byte) 0xAC, (byte) 0x89 };
+
+ /** Font index MO:DCA structured field. */
+ private static final byte[] FONT_INDEX_SF = new byte[] {
+ (byte) 0xD3, (byte) 0x8C, (byte) 0x89 };
+
+ /**
+ * The conversion factor to millipoints for 240 dpi
+ */
+ private static final int FOP_100_DPI_FACTOR = 1;
+
+ /**
+ * The conversion factor to millipoints for 240 dpi
+ */
+ private static final int FOP_240_DPI_FACTOR = 300000;
+
+ /**
+ * The conversion factor to millipoints for 300 dpi
+ */
+ private static final int FOP_300_DPI_FACTOR = 240000;
+
+ /**
+ * The encoding to use to convert from EBCIDIC to ASCII
+ */
+ private static final String ASCII_ENCODING = "UTF8";
+
+ /**
+ * The collection of code pages
+ */
+ private final Map/*<String, Map<String, String>>*/ codePages
+ = new java.util.HashMap/*<String, Map<String, String>>*/();
+
+ /**
+ * Returns an InputStream to a given file path and filename
+ *
+ * @param path the file path
+ * @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(String path, String filename) throws IOException {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = AFPFontReader.class.getClassLoader();
+ }
+
+ URL url = classLoader.getResource(path);
+
+ if (url == null) {
+ try {
+ File file = new File(path);
+ url = file.toURI().toURL();
+ if (url == null) {
+ String msg = "file not found " + filename + " in classpath: " + path;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+ } catch (MalformedURLException ex) {
+ String msg = "file not found " + filename + " in classpath: " + path;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+ }
+
+ File directory = new File(url.getPath());
+ if (!directory.canRead()) {
+ String msg = "Failed to read directory " + url.getPath();
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+
+ final String filterpattern = filename.trim();
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.startsWith(filterpattern);
+ }
+ };
+
+ File[] files = directory.listFiles(filter);
+
+ if (files.length < 1) {
+ String msg = "file search for " + filename + " located "
+ + files.length + " files";
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ } else if (files.length > 1) {
+ String msg = "file search for " + filename + " located "
+ + files.length + " files";
+ log.warn(msg);
+ }
+
+ InputStream inputStream = files[0].toURI().toURL().openStream();
+
+ if (inputStream == null) {
+ String msg = "AFPFontReader:: getInputStream():: file not found for " + filename;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+
+ return inputStream;
+ }
+
+ /**
+ * Closes the inputstream
+ *
+ * @param inputStream the inputstream to close
+ */
+ private void closeInputStream(InputStream inputStream) {
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } catch (Exception ex) {
+ // Lets log at least!
+ log.error(ex.getMessage());
+ }
+ }
+
+ /**
+ * Load the font details and metrics into the CharacterSetMetric object,
+ * this will use the actual afp code page and character set files to load
+ * the object with the necessary metrics.
+ *
+ * @param characterSet the CharacterSetMetric object to populate
+ * @throws IOException if an I/O exception of some sort has occurred.
+ */
+ public void loadCharacterSetMetric(CharacterSet characterSet) throws IOException {
+
+ InputStream inputStream = null;
+
+ try {
+
+ /**
+ * Get the code page which contains the character mapping
+ * information to map the unicode character id to the graphic
+ * chracter global identifier.
+ */
+ String codePageId = new String(characterSet.getCodePage());
+ String path = characterSet.getPath();
+
+ Map/*<String,String>*/ codePage = (Map/*<String,String>*/)codePages.get(codePageId);
+
+ if (codePage == null) {
+ codePage = loadCodePage(codePageId, characterSet.getEncoding(), path);
+ codePages.put(codePageId, codePage);
+ }
+
+ /**
+ * Load the character set metric information, no need to cache this
+ * information as it should be cached by the objects that wish to
+ * load character set metric information.
+ */
+ final String characterSetName = characterSet.getName();
+
+ inputStream = openInputStream(path, characterSetName);
+
+ StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream);
+
+ // Process D3A789 Font Control
+ FontControl fontControl = processFontControl(structuredFieldReader);
+
+ if (fontControl != null) {
+ //process D3AE89 Font Orientation
+ CharacterSetOrientation[] characterSetOrientations
+ = processFontOrientation(structuredFieldReader);
+
+ int dpi = fontControl.getDpi();
+
+ //process D3AC89 Font Position
+ processFontPosition(structuredFieldReader, characterSetOrientations, dpi);
+
+ //process D38C89 Font Index (per orientation)
+ for (int i = 0; i < characterSetOrientations.length; i++) {
+ processFontIndex(structuredFieldReader,
+ characterSetOrientations[i], codePage, dpi);
+ characterSet.addCharacterSetOrientation(characterSetOrientations[i]);
+ }
+ } else {
+ throw new IOException(
+ "Failed to read font control structured field in character set "
+ + characterSetName);
+ }
+
+ } finally {
+ closeInputStream(inputStream);
+ }
+
+ }
+
+ /**
+ * Load the code page information from the appropriate file. The file name
+ * to load is determined by the code page name and the file extension 'CDP'.
+ *
+ * @param codePage
+ * the code page identifier
+ * @param encoding
+ * the encoding to use for the character decoding
+ * @returns a code page mapping
+ */
+ private Map/*<String,String>*/ loadCodePage(String codePage, String encoding,
+ String path) throws IOException {
+
+ // Create the HashMap to store code page information
+ Map/*<String,String>*/ codePages = new java.util.HashMap/*<String,String>*/();
+
+ InputStream inputStream = null;
+ try {
+ inputStream = openInputStream(path, codePage.trim());
+
+ StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream);
+ byte[] data = structuredFieldReader.getNext(CHARACTER_TABLE_SF);
+
+ int position = 0;
+ byte[] gcgiBytes = new byte[8];
+ byte[] charBytes = new byte[1];
+
+ // 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) {
+ position = 0;
+ // Set the character
+ charBytes[0] = data[index];
+ String gcgiString = new String(gcgiBytes,
+ AFPConstants.EBCIDIC_ENCODING);
+ String charString = new String(charBytes, encoding);
+// int value = charString.charAt(0);
+ codePages.put(gcgiString, charString);
+ } else {
+ position++;
+ }
+ }
+ } finally {
+ closeInputStream(inputStream);
+ }
+
+ return codePages;
+ }
+
+ /**
+ * Process the font control details using the structured field reader.
+ *
+ * @param structuredFieldReader
+ * the structured field reader
+ */
+ private FontControl processFontControl(StructuredFieldReader structuredFieldReader)
+ throws IOException {
+
+ byte[] fncData = structuredFieldReader.getNext(FONT_CONTROL_SF);
+
+// int position = 0;
+ FontControl fontControl = null;
+ if (fncData != null) {
+ fontControl = new FontControl();
+
+ if (fncData[7] == (byte) 0x02) {
+ fontControl.setRelative(true);
+ }
+
+ int dpi = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10;
+
+ fontControl.setDpi(dpi);
+ }
+ return fontControl;
+ }
+
+ /**
+ * Process the font orientation details from using the structured field
+ * reader.
+ *
+ * @param structuredFieldReader
+ * the structured field reader
+ */
+ private 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");
+ }
+
+ CharacterSetOrientation cso = new CharacterSetOrientation(
+ orientation);
+ orientations.add(cso);
+
+ }
+ }
+
+ return (CharacterSetOrientation[]) orientations
+ .toArray(EMPTY_CSO_ARRAY);
+ }
+
+ /**
+ * Populate the CharacterSetOrientation object in the suplied array with the
+ * font position details using the supplied structured field reader.
+ *
+ * @param structuredFieldReader
+ * the structured field reader
+ * @param characterSetOrientations
+ * the array of CharacterSetOrientation objects
+ */
+ private void processFontPosition(StructuredFieldReader structuredFieldReader,
+ CharacterSetOrientation[] characterSetOrientations, int dpi) throws IOException {
+
+ byte[] data = structuredFieldReader.getNext(FONT_POSITION_SF);
+
+ int position = 0;
+ byte[] fpData = new byte[26];
+
+ int characterSetOrientationIndex = 0;
+ int fopFactor = 0;
+
+ switch (dpi) {
+ case 100:
+ fopFactor = FOP_100_DPI_FACTOR;
+ break;
+ case 240:
+ fopFactor = FOP_240_DPI_FACTOR;
+ break;
+ case 300:
+ fopFactor = FOP_300_DPI_FACTOR;
+ break;
+ default:
+ String msg = "Unsupported font resolution of " + dpi + " dpi.";
+ log.error(msg);
+ throw new IOException(msg);
+ }
+
+ // Read data, ignoring bytes 0 - 2
+ for (int index = 3; index < data.length; index++) {
+ if (position < 22) {
+ // Build the font orientation record
+ fpData[position] = data[index];
+ } else if (position == 22) {
+
+ position = 0;
+
+ CharacterSetOrientation characterSetOrientation
+ = characterSetOrientations[characterSetOrientationIndex];
+
+ int xHeight = ((fpData[2] & 0xFF) << 8) + (fpData[3] & 0xFF);
+ int capHeight = ((fpData[4] & 0xFF) << 8) + (fpData[5] & 0xFF);
+ int ascHeight = ((fpData[6] & 0xFF) << 8) + (fpData[7] & 0xFF);
+ int dscHeight = ((fpData[8] & 0xFF) << 8) + (fpData[9] & 0xFF);
+
+ dscHeight = dscHeight * -1;
+
+ characterSetOrientation.setXHeight(xHeight * fopFactor);
+ characterSetOrientation.setCapHeight(capHeight * fopFactor);
+ characterSetOrientation.setAscender(ascHeight * fopFactor);
+ characterSetOrientation.setDescender(dscHeight * fopFactor);
+
+ characterSetOrientationIndex++;
+
+ fpData[position] = data[index];
+
+ }
+
+ position++;
+ }
+
+ }
+
+ /**
+ * Process the font index details for the character set orientation.
+ *
+ * @param structuredFieldReader
+ * the structured field reader
+ * @param cso
+ * the CharacterSetOrientation object to populate
+ * @param codepage
+ * the map of code pages
+ */
+ private void processFontIndex(StructuredFieldReader structuredFieldReader,
+ CharacterSetOrientation cso, Map/*<String,String>*/ codepage, int dpi)
+ throws IOException {
+
+ byte[] data = structuredFieldReader.getNext(FONT_INDEX_SF);
+
+ int fopFactor = 0;
+
+ switch (dpi) {
+ case 100:
+ fopFactor = FOP_100_DPI_FACTOR;
+ break;
+ case 240:
+ fopFactor = FOP_240_DPI_FACTOR;
+ break;
+ case 300:
+ fopFactor = FOP_300_DPI_FACTOR;
+ break;
+ default:
+ String msg = "Unsupported font resolution of " + dpi + " dpi.";
+ log.error(msg);
+ throw new IOException(msg);
+ }
+
+ int position = 0;
+
+ byte[] gcgid = new byte[8];
+ byte[] fiData = new byte[20];
+
+ int lowest = 255;
+ int highest = 0;
+
+ // Read data, ignoring bytes 0 - 2
+ for (int index = 3; index < data.length; index++) {
+ if (position < 8) {
+ gcgid[position] = data[index];
+ position++;
+ } else if (position < 27) {
+ fiData[position - 8] = data[index];
+ position++;
+ } else if (position == 27) {
+
+ fiData[position - 8] = data[index];
+
+ position = 0;
+
+ String gcgiString = new String(gcgid, AFPConstants.EBCIDIC_ENCODING);
+
+ String idx = (String) codepage.get(gcgiString);
+
+ if (idx != null) {
+
+ int cidx = idx.charAt(0);
+ int width = ((fiData[0] & 0xFF) << 8) + (fiData[1] & 0xFF);
+
+ if (cidx < lowest) {
+ lowest = cidx;
+ }
+
+ if (cidx > highest) {
+ highest = cidx;
+ }
+
+ int a = (width * fopFactor);
+
+ cso.setWidth(cidx, a);
+
+ }
+
+ }
+ }
+
+ cso.setFirstChar(lowest);
+ cso.setLastChar(highest);
+
+ }
+
+ private class FontControl {
+
+ private int dpi;
+
+ private boolean isRelative = false;
+
+ public int getDpi() {
+ return dpi;
+ }
+
+ public void setDpi(int i) {
+ dpi = i;
+ }
+
+ public boolean isRelative() {
+ return isRelative;
+ }
+
+ public void setRelative(boolean b) {
+ isRelative = b;
+ }
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java
new file mode 100644
index 000000000..ee7a3c0eb
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+/**
+ * Holds the current page fonts
+ */
+public class AFPPageFonts extends java.util.HashMap {
+ private static final long serialVersionUID = -4991896259427109041L;
+
+ /**
+ * Default constructor
+ */
+ public AFPPageFonts() {
+ super();
+ }
+
+ /**
+ * Parameterized constructor
+ *
+ * @param fonts an existing set of afp page fonts
+ */
+ public AFPPageFonts(AFPPageFonts fonts) {
+ super(fonts);
+ }
+
+ /**
+ * Registers a font on the current page and returns font attributes
+ *
+ * @param fontName the internal font name
+ * @param font the AFPFont
+ * @param fontSize the font point size
+ * @return newly registered AFPFontAttributes
+ */
+ public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
+ String pageFontKey = fontName + "_" + fontSize;
+ AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
+ // Add to page font mapping if not already present
+ if (afpFontAttributes == null) {
+ afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
+ super.put(pageFontKey, afpFontAttributes);
+ int fontRef = super.size();
+ afpFontAttributes.setFontReference(fontRef);
+ }
+ return afpFontAttributes;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java
new file mode 100644
index 000000000..31b53bf08
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java
@@ -0,0 +1,318 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.StringUtils;
+
+/**
+ * The IBM Font Object Content Architecture (FOCA) supports presentation
+ * of character shapes by defining their characteristics, which include
+ * font description information for identifying the characters, font metric
+ * information for positioning the characters, and character shape information
+ * for presenting the character images.
+ * <p/>
+ * Presenting a graphic character on a presentation surface requires
+ * information on the rotation and position of character on the physical
+ * or logical page.
+ * <p/>
+ * This class proivdes font metric information for a particular font
+ * as identified by the character set name. This information is obtained
+ * directly from the AFP font files which must be installed in the path
+ * specified in the afp-fonts xml definition file.
+ * <p/>
+ */
+public class CharacterSet {
+
+ /** Static logging instance */
+ protected static final Log log = LogFactory.getLog(CharacterSet.class.getName());
+
+ /** default codepage */
+ public static final String DEFAULT_CODEPAGE = "T1V10500";
+
+ /** default encoding */
+ public static final String DEFAULT_ENCODING = "Cp500";
+
+ private static final int MAX_NAME_LEN = 8;
+
+
+ /** The code page to which the character set relates */
+ protected String codePage;
+
+ /** The encoding used for the code page */
+ protected String encoding;
+
+ /** The character set relating to the font */
+ protected String name;
+
+ /** The path to the installed fonts */
+ protected String path;
+
+ /** Indicator as to whether to metrics have been loaded */
+ private boolean isMetricsLoaded = false;
+
+ /** The current orientation (currently only 0 is supported by FOP) */
+ private final String currentOrientation = "0";
+
+ /** The collection of objects for each orientation */
+ private Map characterSetOrientations = null;
+
+ /**
+ * Constructor for the CharacterSetMetric object, the character set is used
+ * to load the font information from the actual AFP font.
+ *
+ * @param codePage the code page identifier
+ * @param encoding the encoding of the font
+ * @param name the character set name
+ * @param path the path to the installed afp fonts
+ */
+ public CharacterSet(String codePage, String encoding, String name, String path) {
+ 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);
+ throw new IllegalArgumentException(msg);
+ }
+
+ if (name.length() < MAX_NAME_LEN) {
+ this.name = StringUtils.rpad(name, ' ', MAX_NAME_LEN);
+ } else {
+ this.name = name;
+ }
+ this.codePage = codePage;
+ this.encoding = encoding;
+ this.path = path;
+
+ this.characterSetOrientations = new java.util.HashMap(4);
+ }
+
+ /**
+ * Add character set metric information for the different orientations
+ *
+ * @param cso the metrics for the orientation
+ */
+ public void addCharacterSetOrientation(CharacterSetOrientation cso) {
+ characterSetOrientations.put(
+ String.valueOf(cso.getOrientation()),
+ cso);
+ }
+
+ /**
+ * 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
+ * a character rotation other than 0, ascender height loses its
+ * meaning when the character is lying on its side or is upside down
+ * with respect to normal viewing orientation. For the general case,
+ * Ascender Height is the characters most positive y-axis value.
+ * For bounded character boxes, for a given character having an
+ * ascender, ascender height and baseline offset are equal.
+ *
+ * @return the ascender value in millipoints
+ */
+ public int getAscender() {
+ load();
+ return getCharacterSetOrientation().getAscender();
+ }
+
+ /**
+ * Cap height is the average height of the uppercase characters in
+ * a font. This value is specified by the designer of a font and is
+ * usually the height of the uppercase M.
+ *
+ * @return the cap height value in millipoints
+ */
+ public int getCapHeight() {
+ load();
+ return getCharacterSetOrientation().getCapHeight();
+ }
+
+ /**
+ * Descender depth is the distance from the character baseline to
+ * the bottom of a character box. A negative descender depth signifies
+ * that all of the graphic character is above the character baseline.
+ *
+ * @return the descender value in millipoints
+ */
+ public int getDescender() {
+ load();
+ return getCharacterSetOrientation().getDescender();
+ }
+
+ /**
+ * Returns the first character in the character set
+ *
+ * @return the first character in the character set
+ */
+ public int getFirstChar() {
+ load();
+ return getCharacterSetOrientation().getFirstChar();
+ }
+
+ /**
+ * Returns the last character in the character set
+ *
+ * @return the last character in the character set
+ */
+ public int getLastChar() {
+ load();
+ return getCharacterSetOrientation().getLastChar();
+ }
+
+ /**
+ * Returns the path where the font resources are installed
+ *
+ * @return the path where the font resources are installed
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Get the width (in 1/1000ths of a point size) of all characters
+ *
+ * @return the widths of all characters
+ */
+ public int[] getWidths() {
+ load();
+ return getCharacterSetOrientation().getWidths();
+ }
+
+ /**
+ * XHeight refers to the height of the lower case letters above the baseline.
+ *
+ * @return the typical height of characters
+ */
+ public int getXHeight() {
+ load();
+ return getCharacterSetOrientation().getXHeight();
+ }
+
+ /**
+ * Get the width (in 1/1000ths of a point size) of the character
+ * identified by the parameter passed.
+ *
+ * @param character the character from which the width will be calculated
+ * @return the width of the character
+ */
+ public int getWidth(int character) {
+ load();
+ return getCharacterSetOrientation().getWidth(character);
+ }
+
+ /**
+ * Lazy creation of the character metrics, the afp font file will only
+ * be processed on a method call requiring the metric information.
+ */
+ 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);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Returns the AFP character set identifier
+ *
+ * @return the AFP character set identifier
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the AFP character set identifier as a byte array
+ *
+ * @return the AFP character set identifier as a byte array
+ */
+ public byte[] getNameBytes() {
+ byte[] nameBytes = null;
+ try {
+ nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ } catch (UnsupportedEncodingException usee) {
+ nameBytes = name.getBytes();
+ log.warn(
+ "UnsupportedEncodingException translating the name " + name);
+ }
+ return nameBytes;
+ }
+
+ /**
+ * Returns the AFP code page identifier
+ *
+ * @return the AFP code page identifier
+ */
+ public String getCodePage() {
+ return codePage;
+ }
+
+ /**
+ * Returns the AFP code page encoding
+ *
+ * @return the AFP code page encoding
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Helper method to return the current CharacterSetOrientation, note
+ * that FOP does not yet implement the "reference-orientation"
+ * attribute therefore we always use the orientation zero degrees,
+ * Other orientation information is captured for use by a future
+ * implementation (whenever FOP implement the mechanism). This is also
+ * the case for landscape prints which use an orientation of 270 degrees,
+ * in 99.9% of cases the font metrics will be the same as the 0 degrees
+ * therefore the implementation currently will always use 0 degrees.
+ *
+ * @return characterSetOrentation The current orientation metrics.
+ */
+ private CharacterSetOrientation getCharacterSetOrientation() {
+ CharacterSetOrientation c
+ = (CharacterSetOrientation) characterSetOrientations.get(currentOrientation);
+ return c;
+ }
+
+ /**
+ * Map a Unicode character to a code point in the font.
+ * The code tables are already converted to Unicode therefore
+ * we can use the identity mapping.
+ *
+ * @param c character to map
+ * @return the mapped character
+ */
+ public char mapChar(char c) {
+ return c;
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java
new file mode 100644
index 000000000..88e99eccf
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java
@@ -0,0 +1,275 @@
+/*
+ * 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;
+
+/**
+ * The IBM Font Object Content Architecture (FOCA) supports presentation
+ * of character shapes by defining their characteristics, which include
+ * Font-Description information for identifying the characters, Font-Metric
+ * information for positioning the characters, and Character-Shape
+ * information for presenting the character images.
+ *
+ * Presenting a graphic character on a presentation surface requires
+ * that you communicate this information clearly to rotate and position
+ * characters correctly on the physical or logical page.
+ *
+ * This class provides font metric information for a particular font
+ * as by the orientation.
+ *
+ * This information is obtained directly from the AFP font files which must
+ * be installed in the classpath under in the location specified by the path
+ * attribute in the afp-font.xml file.
+ * <p/>
+ */
+public class CharacterSetOrientation {
+
+ /**
+ * The code page to which the character set relates
+ */
+ private String codePage;
+
+ /**
+ * The encoding used for the code page
+ */
+ private String encoding;
+
+ /**
+ * The ascender height for the character set
+ */
+ private int ascender;
+
+ /**
+ * The descender depth for the character set
+ */
+ private int descender;
+
+ /**
+ * The height of capital letters
+ */
+ private int capHeight;
+
+ /**
+ * The characters in the charcater set
+ */
+ private int[] chars = new int[256];
+
+ /**
+ * The height of lowercase letters
+ */
+ private int xHeight;
+
+ /**
+ * The first character
+ */
+ private int firstChar;
+
+ /**
+ * The last character
+ */
+ private int lastChar;
+
+
+ /**
+ * The character set orientation
+ */
+ private int orientation = 0;
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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
+ * a character rotation other than 0, ascender height loses its
+ * meaning when the character is lying on its side or is upside down
+ * with respect to normal viewing orientation. For the general case,
+ * Ascender Height is the character�s most positive y-axis value.
+ * For bounded character boxes, for a given character having an
+ * ascender, ascender height and baseline offset are equal.
+ * @return the ascender value in millipoints
+ */
+ public int getAscender() {
+ return ascender;
+ }
+
+ /**
+ * Cap height is the average height of the uppercase characters in
+ * a font. This value is specified by the designer of a font and is
+ * usually the height of the uppercase M.
+ * @return the cap height value in millipoints
+ */
+ public int getCapHeight() {
+ return capHeight;
+ }
+
+ /**
+ * Descender depth is the distance from the character baseline to
+ * the bottom of a character box. A negative descender depth signifies
+ * that all of the graphic character is above the character baseline.
+ * @return the descender value in millipoints
+ */
+ public int getDescender() {
+ return descender;
+ }
+
+ /**
+ * The first character in the character set
+ * @return the first character
+ */
+ public int getFirstChar() {
+ return firstChar;
+ }
+
+ /**
+ * The last character in the character set
+ * @return the last character
+ */
+ public int getLastChar() {
+ return lastChar;
+ }
+
+ /**
+ * The orientation for these metrics in the character set
+ * @return the orientation
+ */
+ public int getOrientation() {
+ return orientation;
+ }
+
+ /**
+ * Get the width (in 1/1000ths of a point size) of all characters
+ * in this character set.
+ * @return the widths of all characters
+ */
+ public int[] getWidths() {
+ int arr[] = new int[(getLastChar() - getFirstChar()) + 1];
+ System.arraycopy(chars, getFirstChar(), arr, 0, (getLastChar() - getFirstChar()) + 1);
+ return arr;
+ }
+
+ /**
+ * XHeight refers to the height of the lower case letters above
+ * the baseline.
+ * @return heightX the typical height of characters
+ */
+ public int getXHeight() {
+ return xHeight;
+ }
+
+ /**
+ * Get the width (in 1/1000ths of a point size) of the character
+ * identified by the parameter passed.
+ * @param characterIndex the character to evaluate
+ * @return the widths of the character
+ */
+ public int getWidth(int characterIndex) {
+ if (characterIndex >= chars.length) {
+ throw new IllegalArgumentException("Invalid character index: "
+ + characterIndex + ", maximum is " + (chars.length - 1));
+ }
+ return chars[characterIndex];
+ }
+
+ /**
+ * 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
+ * a character rotation other than 0, ascender height loses its
+ * meaning when the character is lying on its side or is upside down
+ * with respect to normal viewing orientation. For the general case,
+ * Ascender Height is the character�s most positive y-axis value.
+ * For bounded character boxes, for a given character having an
+ * ascender, ascender height and baseline offset are equal.
+ * @param ascender the ascender to set
+ */
+ public void setAscender(int ascender) {
+ this.ascender = ascender;
+ }
+
+ /**
+ * Cap height is the average height of the uppercase characters in
+ * a font. This value is specified by the designer of a font and is
+ * usually the height of the uppercase M.
+ * @param capHeight the cap height to set
+ */
+ public void setCapHeight(int capHeight) {
+ this.capHeight = capHeight;
+ }
+
+ /**
+ * Descender depth is the distance from the character baseline to
+ * the bottom of a character box. A negative descender depth signifies
+ * that all of the graphic character is above the character baseline.
+ * @param descender the descender value in millipoints
+ */
+ public void setDescender(int descender) {
+ this.descender = descender;
+ }
+
+ /**
+ * The first character in the character set
+ * @param firstChar the first character
+ */
+ public void setFirstChar(int firstChar) {
+ this.firstChar = firstChar;
+ }
+
+ /**
+ * The last character in the character set
+ * @param lastChar the last character
+ */
+ public void setLastChar(int lastChar) {
+ this.lastChar = lastChar;
+ }
+
+ /**
+ * Set the width (in 1/1000ths of a point size) of the character
+ * identified by the parameter passed.
+ * @param character the character for which the width is being set
+ * @param width the widths of the character
+ */
+ public void setWidth(int character, int width) {
+
+ if (character >= chars.length) {
+ // Increase the size of the array if necessary
+ int arr[] = new int[(character - firstChar) + 1];
+ System.arraycopy(chars, 0, arr, 0, chars.length);
+ chars = arr;
+ }
+ chars[character] = width;
+
+ }
+
+ /**
+ * XHeight refers to the height of the lower case letters above
+ * the baseline.
+ * @param xHeight the typical height of characters
+ */
+ public void setXHeight(int xHeight) {
+ this.xHeight = xHeight;
+ }
+}
diff --git a/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java b/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java
new file mode 100644
index 000000000..86e41707f
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java
@@ -0,0 +1,48 @@
+/*
+ * 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 runtime exception for handling fatal errors in processing fonts.
+ * <p/>
+ */
+public class FontRuntimeException extends RuntimeException {
+
+ private static final long serialVersionUID = -2217420523816384707L;
+
+ /**
+ * Constructs a FontRuntimeException with the specified message.
+ * @param msg the exception mesaage
+ */
+ public FontRuntimeException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a FontRuntimeException with the specified message
+ * wrapping the underlying exception.
+ * @param msg the exception mesaage
+ * @param t the underlying exception
+ */
+ public FontRuntimeException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
new file mode 100644
index 000000000..aec220b40
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java
@@ -0,0 +1,137 @@
+/*
+ * 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;
+
+import org.apache.fop.fonts.Typeface;
+
+/**
+ * A Character set for a normal FOP font<p/>
+ */
+public class FopCharacterSet extends CharacterSet {
+
+ /** The character set for this font */
+ private Typeface charSet = null;
+
+ /**
+ * Constructor for the CharacterSetMetric object, the character set is used
+ * to load the font information from the actual AFP font.
+ * @param codePage the code page identifier
+ * @param encoding the encoding of the font
+ * @param name the character set name
+ * @param charSet the fop character set
+ */
+ public FopCharacterSet(
+ String codePage,
+ String encoding,
+ String name,
+ Typeface charSet) {
+
+ super(codePage, encoding, name, null);
+ this.charSet = charSet;
+ }
+
+ /**
+ * 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
+ * a character rotation other than 0, ascender height loses its
+ * meaning when the character is lying on its side or is upside down
+ * with respect to normal viewing orientation. For the general case,
+ * Ascender Height is the character�s most positive y-axis value.
+ * For bounded character boxes, for a given character having an
+ * ascender, ascender height and baseline offset are equal.
+ * @return the ascender value in millipoints
+ */
+ public int getAscender() {
+ return charSet.getAscender(1);
+ }
+
+ /**
+ * Cap height is the average height of the uppercase characters in
+ * a font. This value is specified by the designer of a font and is
+ * usually the height of the uppercase M.
+ * @return the cap height value in millipoints
+ */
+ public int getCapHeight() {
+ return charSet.getCapHeight(1);
+ }
+
+ /**
+ * Descender depth is the distance from the character baseline to
+ * the bottom of a character box. A negative descender depth signifies
+ * that all of the graphic character is above the character baseline.
+ * @return the descender value in millipoints
+ */
+ public int getDescender() {
+ return charSet.getDescender(1);
+ }
+
+ /**
+ * The first character in the character set
+ * @return the first character
+ */
+ public int getFirstChar() {
+ return 0;
+ }
+
+ /**
+ * The last character in the character set
+ * @return the last character
+ */
+ public int getLastChar() {
+ return 0;
+ }
+
+ /**
+ * Get the width (in 1/1000ths of a point size) of all characters
+ * @return the widths of all characters
+ */
+ public int[] getWidths() {
+ return charSet.getWidths();
+ }
+
+ /**
+ * XHeight refers to the height of the lower case letters above the baseline.
+ * @return the typical height of characters
+ */
+ public int getXHeight() {
+ return charSet.getXHeight(1);
+ }
+
+ /**
+ * Get the width (in 1/1000ths of a point size) of the character
+ * identified by the parameter passed.
+ * @param character the character from which the width will be calculated
+ * @return the width of the character
+ */
+ public int getWidth(int character) {
+ return charSet.getWidth(character, 1);
+ }
+
+ /**
+ * 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);
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/afp/fonts/OutlineFont.java
new file mode 100644
index 000000000..ac45a2467
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/OutlineFont.java
@@ -0,0 +1,182 @@
+/*
+ * 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. <p/>
+ *
+ */
+public class OutlineFont extends AFPFont {
+
+ /** 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
+ */
+ public OutlineFont(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 point size
+ * @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 point size
+ * @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 point size
+ * @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 point size
+ * @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 point size
+ * @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 point size
+ * @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);
+ }
+
+ /**
+ * 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
diff --git a/src/java/org/apache/fop/afp/fonts/RasterFont.java b/src/java/org/apache/fop/afp/fonts/RasterFont.java
new file mode 100644
index 000000000..ddce2d4d5
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/RasterFont.java
@@ -0,0 +1,238 @@
+/*
+ * 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;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A font where each character is stored as an array of pixels (a bitmap). Such
+ * fonts are not easily scalable, in contrast to vectored fonts. With this type
+ * of font, the font metrics information is held in character set files (one for
+ * each size and style). <p/>
+ *
+ */
+public class RasterFont extends AFPFont {
+
+ /** Static logging instance */
+ protected static final Log log = LogFactory.getLog("org.apache.fop.afp.fonts");
+
+ private final Map/*<String,CharacterSet>*/ charSets
+ = new java.util.HashMap/*<String,CharacterSet>*/();
+
+ private CharacterSet charSet = null;
+
+ /**
+ * Constructor for the raster font requires the name, weight and style
+ * attribute to be available as this forms the key to the font.
+ *
+ * @param name
+ * the name of the font
+ */
+ public RasterFont(String name) {
+ super(name);
+ }
+
+ /**
+ * Adds the character set for the given point size
+ * @param size point size
+ * @param characterSet character set
+ */
+ public void addCharacterSet(int size, CharacterSet characterSet) {
+ this.charSets.put(String.valueOf(size), characterSet);
+ this.charSet = characterSet;
+ }
+
+ /** Describes the unit millipoint. */
+ public static final String MPT = "mpt";
+
+ /**
+ * Get the character set metrics for the specified point size.
+ *
+ * @param size the point size
+ * @return the character set metrics
+ */
+ public CharacterSet getCharacterSet(int size) {
+
+ String pointsize = String.valueOf(size / 1000);
+ CharacterSet csm = (CharacterSet) charSets.get(pointsize);
+ if (csm == null) {
+ csm = (CharacterSet) charSets.get(size + MPT);
+ }
+ if (csm == null) {
+ // Get char set with nearest font size
+ int distance = Integer.MAX_VALUE;
+ for (Iterator it = charSets.entrySet().iterator(); it.hasNext();) {
+ Map.Entry me = (Map.Entry)it.next();
+ String key = (String)me.getKey();
+ if (!key.endsWith(MPT)) {
+ int mpt = Integer.parseInt(key) * 1000;
+ if (Math.abs(size - mpt) < distance) {
+ distance = Math.abs(size - mpt);
+ pointsize = (String)me.getKey();
+ csm = (CharacterSet)me.getValue();
+ }
+ }
+ }
+ if (csm != null) {
+ charSets.put(size + MPT, csm);
+ String msg = "No " + (size / 1000) + "pt font " + getFontName()
+ + " found, substituted with " + pointsize + "pt font";
+ log.warn(msg);
+ }
+ }
+ if (csm == null) {
+ String msg = "No font found for font " + getFontName()
+ + " with point size " + pointsize;
+ log.error(msg);
+ throw new FontRuntimeException(msg);
+ }
+ return csm;
+
+ }
+
+ /**
+ * Get the first character in this font.
+ * @return the first character in this font.
+ */
+ public int getFirstChar() {
+ Iterator it = charSets.values().iterator();
+ if (it.hasNext()) {
+ CharacterSet csm = (CharacterSet) it.next();
+ return csm.getFirstChar();
+ } else {
+ String msg = "getFirstChar() - No character set found for font:" + getFontName();
+ log.error(msg);
+ throw new FontRuntimeException(msg);
+ }
+ }
+
+ /**
+ * Get the last character in this font.
+ * @return the last character in this font.
+ */
+ public int getLastChar() {
+
+ Iterator it = charSets.values().iterator();
+ if (it.hasNext()) {
+ CharacterSet csm = (CharacterSet) it.next();
+ return csm.getLastChar();
+ } else {
+ String msg = "getLastChar() - No character set found for font:" + getFontName();
+ log.error(msg);
+ throw new FontRuntimeException(msg);
+ }
+
+ }
+
+ /**
+ * 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 point size
+ * @return the ascender for the given point size
+ */
+ public int getAscender(int size) {
+ return getCharacterSet(size).getAscender() * size;
+ }
+
+ /**
+ * Obtains the height of capital letters for the specified point size.
+ *
+ * @param size the point size
+ * @return the cap height for the specified point size
+ */
+ public int getCapHeight(int size) {
+ return getCharacterSet(size).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 point size
+ * @return the descender for the specified point size
+ */
+ public int getDescender(int size) {
+ return getCharacterSet(size).getDescender() * size;
+ }
+
+ /**
+ * The "x-height" (the height of the letter "x").
+ *
+ * @param size the point size
+ * @return the x height for the given point size
+ */
+ public int getXHeight(int size) {
+ return getCharacterSet(size).getXHeight() * size;
+ }
+
+ /**
+ * Obtain the width of the character for the specified point size.
+ * @param character the character
+ * @param size the point size
+ * @return the width for the given point size
+ */
+ public int getWidth(int character, int size) {
+ return getCharacterSet(size).getWidth(character) * size;
+ }
+
+ /**
+ * Get the getWidth (in 1/1000ths of a point size) of all characters in this
+ * character set.
+ *
+ * @param size
+ * the point size
+ * @return the widths of all characters
+ */
+ public int[] getWidths(int size) {
+ return getCharacterSet(size).getWidths();
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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();
+ }
+
+}
diff --git a/src/java/org/apache/fop/afp/fonts/package.html b/src/java/org/apache/fop/afp/fonts/package.html
new file mode 100644
index 000000000..74f8bf450
--- /dev/null
+++ b/src/java/org/apache/fop/afp/fonts/package.html
@@ -0,0 +1,23 @@
+<!--
+ 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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.goca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Graphics Object Content Architecture (GOCA) structured objects.</P>
+</BODY>
+</HTML> \ No newline at end of file