diff options
Diffstat (limited to 'src/java/org/apache/fop/afp/fonts')
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java | 157 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPFont.java | 113 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java | 106 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPFontCollection.java | 92 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPFontInfo.java | 63 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPFontReader.java | 592 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/AFPPageFonts.java | 64 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/CharacterSet.java | 318 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java | 275 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/FontRuntimeException.java | 48 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/FopCharacterSet.java | 137 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/OutlineFont.java | 182 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/RasterFont.java | 238 | ||||
-rw-r--r-- | src/java/org/apache/fop/afp/fonts/package.html | 23 |
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 |