aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render/afp/fonts
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2006-07-24 13:15:33 +0000
committerJeremias Maerki <jeremias@apache.org>2006-07-24 13:15:33 +0000
commit423453976de29088ee76156baec1a83bc58b9518 (patch)
tree862dc8f568a4debcbd648f69797381df97adece5 /src/java/org/apache/fop/render/afp/fonts
parent0f58ef4c39df7e8525f52325a10e3c1aa1ae5ad9 (diff)
downloadxmlgraphics-fop-423453976de29088ee76156baec1a83bc58b9518.tar.gz
xmlgraphics-fop-423453976de29088ee76156baec1a83bc58b9518.zip
Promoting the AFP renderer from sandbox to the main source tree.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@425037 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop/render/afp/fonts')
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/AFPFont.java92
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java58
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java608
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/CharacterSet.java322
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java275
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java139
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/OutlineFont.java193
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/RasterFont.java243
8 files changed, 1930 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java b/src/java/org/apache/fop/render/afp/fonts/AFPFont.java
new file mode 100644
index 000000000..b7f27d65e
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/AFPFont.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.afp.fonts;
+import java.util.Map;
+import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.Typeface;
+
+
+/**
+ * All implemenations 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) {
+
+ _name = name;
+
+ }
+
+ /**
+ * @return the name of the font.
+ */
+ public String getFontName() {
+ return _name;
+ }
+
+ /**
+ * Returns the type of the font.
+ * @return the font type
+ */
+ public FontType getFontType() {
+ return FontType.OTHER;
+ }
+
+ /**
+ * Indicates if the font has kering 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, Falso otherwise
+ */
+ public boolean hasChar(char c) {
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java
new file mode 100644
index 000000000..ce08d4131
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.afp.fonts;
+
+import java.util.List;
+
+/**
+ * FontInfo contains meta information on fonts
+ */
+public class AFPFontInfo {
+
+ private AFPFont font;
+ private List fontTriplets;
+
+ /**
+ * Main constructor
+ * @param afpFont The AFP Font
+ * @param fontTriplets List of font triplets to associate with this font
+ */
+ public AFPFontInfo(AFPFont afpFont, List fontTriplets) {
+ this.font = afpFont;
+ this.fontTriplets = fontTriplets;
+ }
+
+ /**
+ * 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 getFontTriplets() {
+ return fontTriplets;
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java
new file mode 100644
index 000000000..cb8718d8f
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.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.ArrayList;
+import java.util.HashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.render.afp.exceptions.FontRuntimeException;
+import org.apache.fop.render.afp.modca.AFPConstants;
+import org.apache.fop.render.afp.tools.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.fop.render.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 static HashMap _codePages = new HashMap();
+
+ /**
+ * 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
+ */
+ public static void loadCharacterSetMetric(CharacterSet characterSet) {
+
+ 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 cp = new String(characterSet.getCodePage());
+ String path = characterSet.getPath();
+
+ HashMap codepage = (HashMap) _codePages.get(cp);
+
+ if (codepage == null) {
+ codepage = loadCodePage(cp, characterSet.getEncoding(), path);
+ _codePages.put(cp, 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 characterset = characterSet.getName();
+
+ 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.toURL();
+ if (url == null) {
+ String msg = "CharacterSet file not found for "
+ + characterset + " in classpath: " + path;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+ } catch (MalformedURLException ex) {
+ String msg = "CharacterSet file not found for "
+ + characterset + " in classpath: " + path;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+
+ }
+
+ File directory = new File(url.getPath());
+
+ final String filterpattern = characterset.trim();
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.startsWith(filterpattern);
+ }
+ };
+
+ File[] csfont = directory.listFiles(filter);
+ if (csfont.length < 1) {
+ String msg = "CharacterSet file search for " + characterset
+ + " located " + csfont.length + " files";
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ } else if (csfont.length > 1) {
+ String msg = "CharacterSet file search for " + characterset
+ + " located " + csfont.length + " files";
+ log.warn(msg);
+ }
+
+ inputStream = inputStream = csfont[0].toURL().openStream();
+ if (inputStream == null) {
+ String msg = "Failed to open character set resource "
+ + characterset;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+
+ StructuredFieldReader sfr = new StructuredFieldReader(inputStream);
+
+ // Process D3A789 Font Control
+ FontControl fnc = processFontControl(sfr);
+
+ //process D3AE89 Font Orientation
+ CharacterSetOrientation[] csoArray = processFontOrientation(sfr);
+
+ //process D3AC89 Font Position
+ processFontPosition(sfr, csoArray, fnc.getDpi());
+
+ //process D38C89 Font Index (per orientation)
+ for (int i = 0; i < csoArray.length; i++) {
+ processFontIndex(sfr, csoArray[i], codepage, fnc.getDpi());
+ characterSet.addCharacterSetOrientation(csoArray[i]);
+ }
+
+ } catch (Exception ex) {
+ throw new FontRuntimeException(
+ "Failed to load the character set metrics for code page "
+ + characterSet.getCodePage(), ex);
+ } finally {
+ try {
+ inputStream.close();
+ } catch (Exception ex) {
+ // Ignore
+ }
+ }
+
+ }
+
+ /**
+ * 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
+ */
+ private static HashMap loadCodePage(String codePage, String encoding,
+ String path) throws IOException, FileNotFoundException {
+
+ // Create the HashMap to store code page information
+ HashMap codepages = new HashMap();
+
+ 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.toURL();
+ if (url == null) {
+ String msg = "CodePage file not found for " + codePage
+ + " in classpath: " + path;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+ } catch (MalformedURLException ex) {
+ String msg = "CodePage file not found for " + codePage
+ + " in classpath: " + path;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+
+ }
+
+ File directory = new File(url.getPath());
+
+ final String filterpattern = codePage.trim();
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.startsWith(filterpattern);
+ }
+ };
+
+ File[] codepage = directory.listFiles(filter);
+
+ if (codepage.length < 1) {
+ String msg = "CodePage file search for " + codePage + " located "
+ + codepage.length + " files";
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ } else if (codepage.length > 1) {
+ String msg = "CodePage file search for " + codePage + " located "
+ + codepage.length + " files";
+ log.warn(msg);
+ }
+
+ InputStream is = codepage[0].toURL().openStream();
+
+ if (is == null) {
+ String msg = "AFPFontReader:: loadCodePage(String):: code page file not found for "
+ + codePage;
+ log.error(msg);
+ throw new FileNotFoundException(msg);
+ }
+
+ StructuredFieldReader sfr = new StructuredFieldReader(is);
+ byte[] data = sfr.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++;
+ }
+ }
+
+ try {
+ is.close();
+ } catch (Exception ex) {
+ // Ignore
+ }
+
+ return codepages;
+
+ }
+
+ /**
+ * Process the font control details using the structured field reader.
+ *
+ * @param sfr
+ * the structured field reader
+ */
+ private static FontControl processFontControl(StructuredFieldReader sfr)
+ throws IOException {
+
+ byte[] fncData = sfr.getNext(FONT_CONTROL_SF);
+
+ int position = 0;
+
+ FontControl fontControl = new AFPFontReader().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 sfr
+ * the structured field reader
+ */
+ private static CharacterSetOrientation[] processFontOrientation(
+ StructuredFieldReader sfr) throws IOException {
+
+ byte[] data = sfr.getNext(FONT_ORIENTATION_SF);
+
+ int position = 0;
+ byte[] fnoData = new byte[26];
+
+ ArrayList orientations = new 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 sfr
+ * the structured field reader
+ * @param csoArray
+ * the array of CharacterSetOrientation objects
+ */
+ private static void processFontPosition(StructuredFieldReader sfr,
+ CharacterSetOrientation[] csoArray, int dpi) throws IOException {
+
+ byte[] data = sfr.getNext(FONT_POSITION_SF);
+
+ int position = 0;
+ byte[] fpData = new byte[26];
+
+ int csoIndex = 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 cso = csoArray[csoIndex];
+
+ 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;
+
+ cso.setXHeight(xHeight * fopFactor);
+ cso.setCapHeight(capHeight * fopFactor);
+ cso.setAscender(ascHeight * fopFactor);
+ cso.setDescender(dscHeight * fopFactor);
+
+ csoIndex++;
+
+ fpData[position] = data[index];
+
+ }
+
+ position++;
+ }
+
+ }
+
+ /**
+ * Process the font index details for the character set orientation.
+ *
+ * @param sfr
+ * the structured field reader
+ * @param cso
+ * the CharacterSetOrientation object to populate
+ * @param codepage
+ * the map of code pages
+ */
+ private static void processFontIndex(StructuredFieldReader sfr,
+ CharacterSetOrientation cso, HashMap codepage, int dpi)
+ throws IOException {
+
+ byte[] data = sfr.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] = (byte) data[index];
+ position++;
+ } else if (position < 27) {
+ fiData[position - 8] = (byte) data[index];
+ position++;
+ } else if (position == 27) {
+
+ fiData[position - 8] = (byte) 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;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java
new file mode 100644
index 000000000..ac39eff85
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.afp.fonts;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.render.afp.modca.AFPConstants;
+import org.apache.fop.render.afp.tools.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());
+
+ /**
+ * 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 name of the character set as EBCIDIC bytes
+ */
+ private byte[] _nameBytes;
+
+ /**
+ * 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 suppoted by FOP)
+ */
+ private String _currentOrientation = "0";
+
+ /**
+ * The collection of objects for each orientation
+ */
+ private HashMap _characterSetOrientations;
+
+ /**
+ * 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() > 8) {
+ String msg = "Character set name must be a maximum of 8 characters " + name;
+ log.error("Constructor:: " + msg);
+ throw new IllegalArgumentException(msg);
+ }
+
+ if (name.length() < 8) {
+ _name = StringUtils.rpad(name, ' ', 8);
+ } else {
+ _name = name;
+ }
+
+ try {
+
+ _nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+
+ } catch (UnsupportedEncodingException usee) {
+
+ _nameBytes = name.getBytes();
+ log.warn(
+ "Constructor:: UnsupportedEncodingException translating the name "
+ + name);
+
+ }
+
+ _codePage = codePage;
+ _encoding = encoding;
+ _path = path;
+ _characterSetOrientations = new 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 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() {
+ 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();
+ }
+
+ /**
+ * The first character in the character set
+ * @return the first character
+ */
+ public int getFirstChar() {
+ load();
+ return getCharacterSetOrientation().getFirstChar();
+ }
+
+ /**
+ * The last character in the character set
+ * @return the last character
+ */
+ public int getLastChar() {
+ load();
+ return getCharacterSetOrientation().getLastChar();
+ }
+
+ /**
+ * @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 width(int character) {
+ load();
+ return getCharacterSetOrientation().width(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.loadCharacterSetMetric(this);
+ _isMetricsLoaded = true;
+
+ }
+
+ }
+
+ /**
+ * Returns the AFP character set identifier
+ * @return String
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Returns the AFP character set identifier
+ * @return byte[]
+ */
+ public byte[] getNameBytes() {
+ return _nameBytes;
+ }
+
+ /**
+ * Returns the AFP code page identifier
+ * @return String
+ */
+ public String getCodePage() {
+ return _codePage;
+ }
+
+ /**
+ * Returns the AFP code page encoding
+ * @return String
+ */
+ 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 currely 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/render/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java
new file mode 100644
index 000000000..084edfb5e
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.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 proivdes font metric information for a particular font
+ * as by the orientation.
+ *
+ * This informtaion 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[] _characters = new int[256];
+
+ /**
+ * The height of lowercase letters
+ */
+ private int _xHeight;
+
+ /**
+ * The first character
+ */
+ private int _firstCharacter;
+
+ /**
+ * The last character
+ */
+ private int _lastCharacter;
+
+
+ /**
+ * 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) {
+
+ _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 _firstCharacter;
+ }
+
+ /**
+ * The last character in the character set
+ * @return the last character
+ */
+ public int getLastChar() {
+ return _lastCharacter;
+ }
+
+ /**
+ * 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(_characters, 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 character the character to evaluate
+ * @return the widths of the character
+ */
+ public int width(int character) {
+ return _characters[character];
+ }
+
+ /**
+ * 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) {
+ _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) {
+ _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) {
+ _descender = descender;
+ }
+
+ /**
+ * The first character in the character set
+ * @param firstCharacter the first character
+ */
+ public void setFirstChar(int firstCharacter) {
+ _firstCharacter = firstCharacter;
+ }
+
+ /**
+ * The last character in the character set
+ * @param lastCharacter the last character
+ */
+ public void setLastChar(int lastCharacter) {
+ _lastCharacter = lastCharacter;
+ }
+
+ /**
+ * 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 >= _characters.length) {
+ // Increase the size of the array if necessary
+ int arr[] = new int[(character - _firstCharacter) + 1];
+ System.arraycopy(_characters, 0, arr, 0, _characters.length);
+ _characters = arr;
+ }
+ _characters[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) {
+ _xHeight = xHeight;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java
new file mode 100644
index 000000000..ff8f9240e
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.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 _characterSet = null;
+ private int _size = 0;
+
+ /**
+ * 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 size the font size
+ * @param characterSet the fop character set
+ */
+ public FopCharacterSet(
+ String codePage,
+ String encoding,
+ String name,
+ int size,
+ Typeface characterSet) {
+ super(codePage, encoding, name, null);
+ _characterSet = characterSet;
+ _size = size * 1000;
+ }
+
+ /**
+ * 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 _characterSet.getAscender(_size);
+ }
+
+ /**
+ * 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 _characterSet.getCapHeight(_size);
+ }
+
+ /**
+ * 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 _characterSet.getDescender(_size);
+ }
+
+ /**
+ * 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 _characterSet.getWidths();
+ }
+
+ /**
+ * XHeight refers to the height of the lower case letters above the baseline.
+ * @return the typical height of characters
+ */
+ public int getXHeight() {
+ return _characterSet.getXHeight(_size);
+ }
+
+ /**
+ * 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 width(int character) {
+ return _characterSet.getWidth(character, _size);
+ }
+
+ /**
+ * 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 _characterSet.mapChar(c);
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
new file mode 100644
index 000000000..eabd3f631
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.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 _characterSet = null;
+
+ /**
+ * Constructor for an outline font.
+ *
+ * @param name
+ * the name of the font
+ * @param characterSet
+ * the chracter set
+ */
+ public OutlineFont(String name, CharacterSet characterSet) {
+ super(name);
+ _characterSet = characterSet;
+ }
+
+ /**
+ * Get the character set metrics.
+ *
+ * @return the character set
+ */
+ public CharacterSet getCharacterSet() {
+
+ return _characterSet;
+
+ }
+
+ /**
+ * Get the character set metrics.
+ * @param size ignored
+ * @return the character set
+ */
+ public CharacterSet getCharacterSet(int size) {
+
+ return _characterSet;
+
+ }
+
+ /**
+ * Get the first character in this font.
+ */
+ public int getFirstChar() {
+
+ return _characterSet.getFirstChar();
+
+ }
+
+ /**
+ * Get the last character in this font.
+ */
+ public int getLastChar() {
+
+ return _characterSet.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
+ */
+ public int getAscender(int size) {
+
+ return _characterSet.getAscender() / 1000 * size;
+
+ }
+
+ /**
+ * Obtains the height of capital letters for the specified point size.
+ *
+ * @param size
+ * the point size
+ */
+ public int getCapHeight(int size) {
+
+ return _characterSet.getCapHeight() / 1000 * 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
+ */
+ public int getDescender(int size) {
+
+ return _characterSet.getDescender() / 1000 * size;
+
+ }
+
+ /**
+ * The "x-height" (the height of the letter "x").
+ *
+ * @param size
+ * the point size
+ */
+ public int getXHeight(int size) {
+
+ return _characterSet.getXHeight() / 1000 * size;
+
+ }
+
+ /**
+ * Obtain the width of the character for the specified point size.
+ */
+ public int getWidth(int character, int size) {
+
+ return _characterSet.width(character) / 1000 * 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 = _characterSet.getWidths();
+ for (int i = 0; i < widths.length; i++) {
+ widths[i] = widths[i] / 1000 * 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 _characterSet.mapChar(c);
+ }
+
+ /**
+ * Get the encoding of the font.
+ * @return the encoding
+ */
+ public String getEncoding() {
+ return _characterSet.getEncoding();
+ }
+
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
new file mode 100644
index 000000000..cec80c59c
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.render.afp.fonts;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.render.afp.exceptions.FontRuntimeException;
+
+/**
+ * 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.render.afp.fonts");
+
+ private HashMap _characterSets = new HashMap();
+
+ private CharacterSet _characterSet = 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);
+ }
+
+ public void addCharacterSet(int size, CharacterSet characterSet) {
+
+ _characterSets.put(String.valueOf(size), characterSet);
+
+ _characterSet = characterSet;
+
+ }
+
+ /**
+ * 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) _characterSets.get(pointsize);
+ if (csm == null) {
+ csm = (CharacterSet) _characterSets.get(size + "mpt");
+ }
+ if (csm == null) {
+ // Get char set with nearest font size
+ int distance = Integer.MAX_VALUE;
+ for (Iterator it = _characterSets.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) {
+ _characterSets.put(size + "mpt", csm);
+ String msg = "No " + (size / 1000) + "pt font " + _name
+ + " found, substituted with " + pointsize + "pt font";
+ log.warn(msg);
+ }
+ }
+ if (csm == null) {
+ String msg = "No font found for font " + _name
+ + " with point size " + pointsize;
+ log.error(msg);
+ throw new FontRuntimeException(msg);
+ }
+ return csm;
+
+ }
+
+ /**
+ * Get the first character in this font.
+ */
+ public int getFirstChar() {
+
+ Iterator i = _characterSets.values().iterator();
+ if (i.hasNext()) {
+ CharacterSet csm = (CharacterSet) i.next();
+ return csm.getFirstChar();
+ } else {
+ String msg = "getFirstChar() - No character set found for font:" + _name;
+ log.error(msg);
+ throw new FontRuntimeException(msg);
+ }
+
+ }
+
+ /**
+ * Get the last character in this font.
+ */
+ public int getLastChar() {
+
+ Iterator i = _characterSets.values().iterator();
+ if (i.hasNext()) {
+ CharacterSet csm = (CharacterSet) i.next();
+ return csm.getLastChar();
+ } else {
+ String msg = "getLastChar() - No character set found for font:" + _name;
+ 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
+ */
+ public int getAscender(int size) {
+
+ return getCharacterSet(size).getAscender();
+
+ }
+
+ /**
+ * Obtains the height of capital letters for the specified point size.
+ *
+ * @param size the point size
+ */
+ public int getCapHeight(int size) {
+
+ return getCharacterSet(size).getCapHeight();
+
+ }
+
+ /**
+ * 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
+ */
+ public int getDescender(int size) {
+
+ return getCharacterSet(size).getDescender();
+
+ }
+
+ /**
+ * The "x-height" (the height of the letter "x").
+ *
+ * @param size the point size
+ */
+ public int getXHeight(int size) {
+
+ return getCharacterSet(size).getXHeight();
+
+ }
+
+ /**
+ * Obtain the width of the character for the specified point size.
+ */
+ public int getWidth(int character, int size) {
+
+ return getCharacterSet(size).width(character);
+
+ }
+
+ /**
+ * 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 _characterSet.mapChar(c);
+ }
+
+ /**
+ * Get the encoding of the font.
+ * @return the encoding
+ */
+ public String getEncoding() {
+ return _characterSet.getEncoding();
+ }
+
+} \ No newline at end of file