ASF Bugzilla – Attachment 24857 Details for
Bug 48567
Implementation of support for double-byte fonts by AFP renderer.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch of implementation
48567.patch (text/plain), 77.25 KB, created by
Peter Hancock
on 2010-01-19 02:59:38 UTC
(
hide
)
Description:
patch of implementation
Filename:
MIME Type:
Creator:
Peter Hancock
Created:
2010-01-19 02:59:38 UTC
Size:
77.25 KB
patch
obsolete
>Index: /home/peter/fop_apache/fop_afpfonts/conf/fop.xconf >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/conf/fop.xconf (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/conf/fop.xconf (working copy) >@@ -16,7 +16,7 @@ > <fop version="1.0"> > > <!-- Base URL for resolving relative URLs --> >- <base>.</base> >+ <base>/home/peter/resources/fop/afp_2byte</base> > > <!-- Source resolution in dpi (dots/pixels per inch) for determining the size of pixels in SVG and bitmap images, default: 72dpi --> > <source-resolution>72</source-resolution> >@@ -396,6 +396,37 @@ > <font-triplet name="Courier" style="italic" weight="bold"/> > <font-triplet name="monospace" style="italic" weight="bold"/> > </font> >+ >+ <!-- >+ Configure double-byte (CID Keyed font (Type 0))AFP fonts with type="double-byte". >+ This type is associated with the optional attributes @fallback-type and @fallback-value. >+ >+ @fallback-* specify a fallback for substituting the width metric of characters that lack >+ width metric definition in the font resource. >+ fallback-type={"em", "char"} - default "em". >+ >+ The meaning and value of @fallback-value depends upon the value of @fallback-type as follows: >+ >+ 1- fallback-type="em" (fallback-value ignored) >+ - Use the em width of the font. >+ >+ 2- fallback-type="char" fallback-value="X" >+ - where X is the unicode codepoint (integert) of the character >+ in decimal or hexidecimal (u+xxxx) form. >+ Declares a substitute character to use for the fallback width metric. >+ >+ NOTE no fallback declaration defaults to fallback-type="em" >+ >+ example: >+ <font> >+ <afp-font type="double-byte" encoding="UnicodeBigUnmarked" >+ codepage="T1120000" characterset="CZJHMNU" >+ base-uri="fonts" [fallback-type="char" fallback-value="u+20"] /> >+ <font-triplet name="J-Heisei Mincho" style="normal" weight="normal" /> >+ </font> >+ --> >+ >+ > </fonts> > </renderer> > >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java (working copy) >@@ -30,10 +30,12 @@ > > import org.apache.fop.afp.AFPResourceLevel; > import org.apache.fop.afp.AFPResourceLevelDefaults; >+import org.apache.fop.afp.fonts.AFPFont; > import org.apache.fop.afp.fonts.AFPFontCollection; > import org.apache.fop.afp.fonts.AFPFontInfo; > import org.apache.fop.afp.fonts.CharacterSet; >-import org.apache.fop.afp.fonts.FopCharacterSet; >+import org.apache.fop.afp.fonts.CharacterSetBuilder; >+import org.apache.fop.afp.fonts.DoubleByteFont; > import org.apache.fop.afp.fonts.OutlineFont; > import org.apache.fop.afp.fonts.RasterFont; > import org.apache.fop.afp.util.DefaultFOPResourceAccessor; >@@ -57,7 +59,7 @@ > * AFP Renderer configurator > */ > public class AFPRendererConfigurator extends PrintRendererConfigurator >- implements IFDocumentHandlerConfigurator { >+implements IFDocumentHandlerConfigurator { > > /** > * Default constructor >@@ -69,7 +71,7 @@ > } > > private AFPFontInfo buildFont(Configuration fontCfg, String fontPath) >- throws ConfigurationException { >+ throws ConfigurationException { > > FontManager fontManager = this.userAgent.getFactory().getFontManager(); > >@@ -127,11 +129,33 @@ > return null; > } > String encoding = afpFontCfg.getAttribute("encoding"); >+ > if (encoding == null) { > log.error("Mandatory afp-font configuration attribute 'encoding=' is missing"); > return null; > } > >+ AFPFont font = fontFromType(type, codepage, encoding, accessor, afpFontCfg); >+ >+ return font != null ? new AFPFontInfo(font, tripletList) : null; >+ } >+ >+ >+ /** >+ * Create the AFPFont based on type and type-dependent configuration. >+ * >+ * @param type font type e.g. 'raster', 'outline' >+ * @param codepage codepage file >+ * @param encoding character encoding e.g. 'Cp500', 'UnicodeBigUnmarked' >+ * @param accessor >+ * @param afpFontCfg >+ * @return >+ * @throws ConfigurationException >+ */ >+ private AFPFont fontFromType(String type, String codepage, String encoding, >+ ResourceAccessor accessor, Configuration afpFontCfg) >+ throws ConfigurationException { >+ > if ("raster".equalsIgnoreCase(type)) { > > String name = afpFontCfg.getAttribute("name", "Unknown"); >@@ -161,27 +185,28 @@ > if (base14 != null) { > try { > Class clazz = Class.forName("org.apache.fop.fonts.base14." >- + base14); >+ + base14); > try { > Typeface tf = (Typeface)clazz.newInstance(); >- font.addCharacterSet(sizeMpt, new FopCharacterSet( >- codepage, encoding, characterset, tf)); >+ font.addCharacterSet(sizeMpt, >+ CharacterSetBuilder.getInstance() >+ .build(characterset, codepage, encoding, tf)); > } catch (Exception ie) { > String msg = "The base 14 font class " + clazz.getName() >- + " could not be instantiated"; >+ + " could not be instantiated"; > log.error(msg); > } > } catch (ClassNotFoundException cnfe) { > String msg = "The base 14 font class for " + characterset >- + " could not be found"; >+ + " could not be found"; > log.error(msg); > } > } else { >- font.addCharacterSet(sizeMpt, new CharacterSet( >- codepage, encoding, characterset, accessor)); >+ font.addCharacterSet(sizeMpt, CharacterSetBuilder.getInstance() >+ .build(characterset, codepage, encoding, accessor)); > } > } >- return new AFPFontInfo(font, tripletList); >+ return font; > > } else if ("outline".equalsIgnoreCase(type)) { > String characterset = afpFontCfg.getAttribute("characterset"); >@@ -195,30 +220,83 @@ > if (base14 != null) { > try { > Class clazz = Class.forName("org.apache.fop.fonts.base14." >- + base14); >+ + base14); > try { > Typeface tf = (Typeface)clazz.newInstance(); >- characterSet = new FopCharacterSet( >- codepage, encoding, characterset, tf); >+ characterSet = CharacterSetBuilder.getInstance() >+ .build(characterset, codepage, encoding, tf); > } catch (Exception ie) { > String msg = "The base 14 font class " + clazz.getName() >- + " could not be instantiated"; >+ + " could not be instantiated"; > log.error(msg); > } > } catch (ClassNotFoundException cnfe) { > String msg = "The base 14 font class for " + characterset >- + " could not be found"; >+ + " could not be found"; > log.error(msg); > } > } else { >- characterSet = new CharacterSet(codepage, encoding, characterset, accessor); >+ characterSet = CharacterSetBuilder.getInstance().build( >+ characterset, codepage, encoding, accessor); > } >+ // Return new font object >+ return new OutlineFont(name, characterSet); >+ >+ } else if ("double-byte".equalsIgnoreCase(type)) { >+ String characterset = afpFontCfg.getAttribute("characterset"); >+ if (characterset == null) { >+ log.error("Mandatory afp-font configuration attribute 'characterset=' is missing"); >+ return null; >+ } >+ String name = afpFontCfg.getAttribute("name", characterset); >+ CharacterSet characterSet = null; >+ characterSet = CharacterSetBuilder.getDoubleByteInstance() >+ .build(characterset, codepage, encoding, accessor); >+ > // Create a new font object >- OutlineFont font = new OutlineFont(name, characterSet); >- return new AFPFontInfo(font, tripletList); >+ DoubleByteFont font; >+ >+ String fallbackTypeAttr = afpFontCfg.getAttribute("fallback-type", null); >+ >+ if (fallbackTypeAttr != null) { >+ String fallbackValueAttr = afpFontCfg.getAttribute("fallback-value", null); >+ if (fallbackTypeAttr.equalsIgnoreCase("char") && fallbackValueAttr != null) { >+ >+ try { >+ int fallbackChar; >+ if (fallbackValueAttr.matches("[Uu]\\+.*")) { >+ fallbackChar = Integer.parseInt(fallbackValueAttr.substring(2), 16); >+ } else { >+ fallbackChar = Integer.parseInt(fallbackValueAttr); >+ } >+ >+ font = new DoubleByteFont(name, characterSet, fallbackChar); >+ } catch (NumberFormatException e) { >+ font = new DoubleByteFont(name, characterSet); >+ log.warn("The value of the fallback-value attribute is badly formed: '" >+ + fallbackValueAttr + "' not integral."); >+ } >+ } else if (fallbackTypeAttr.equalsIgnoreCase("em")) { >+ // use the em value >+ font = new DoubleByteFont(name, characterSet); >+ } else { >+ >+ log.warn("The value of the fallback-type attribute '" >+ + fallbackTypeAttr + "' is not recognised."); >+ font = new DoubleByteFont(name, characterSet); >+ } >+ >+ } else { >+ font = new DoubleByteFont(name, characterSet); >+ } >+ >+ >+ return font; >+ > } else { > log.error("No or incorrect type attribute"); > } >+ > return null; > } > >@@ -230,7 +308,7 @@ > * @throws ConfigurationException if something's wrong with the config data > */ > private List/*<AFPFontInfo>*/ buildFontListFromConfiguration(Configuration cfg) >- throws FOPException, ConfigurationException { >+ throws FOPException, ConfigurationException { > > Configuration fonts = cfg.getChild("fonts"); > FontManager fontManager = this.userAgent.getFactory().getFontManager(); >@@ -261,9 +339,9 @@ > FontTriplet triplet = (FontTriplet) fontTriplets.get(j); > if (log.isDebugEnabled()) { > log.debug(" Font triplet " >- + triplet.getName() + ", " >- + triplet.getStyle() + ", " >- + triplet.getWeight()); >+ + triplet.getName() + ", " >+ + triplet.getStyle() + ", " >+ + triplet.getWeight()); > } > > if ((referencedFontsMatcher != null && referencedFontsMatcher.matches(triplet)) >@@ -346,7 +424,7 @@ > > // a default external resource group file setting > Configuration resourceGroupFileCfg >- = cfg.getChild("resource-group-file", false); >+ = cfg.getChild("resource-group-file", false); > if (resourceGroupFileCfg != null) { > String resourceGroupDest = null; > try { >@@ -358,14 +436,15 @@ > customizable.setDefaultResourceGroupFilePath(resourceGroupDest); > } else { > log.warn("Unable to write to default external resource group file '" >- + resourceGroupDest + "'"); >+ + resourceGroupDest + "'"); > } > } > } catch (ConfigurationException e) { > LogUtil.handleException(log, e, > userAgent.getFactory().validateUserConfigStrictly()); > } catch (IOException ioe) { >- throw new FOPException("Could not create default external resource group file", ioe); >+ throw new FOPException("Could not create default external resource group file" >+ , ioe); > } > } > >@@ -401,7 +480,7 @@ > > /** {@inheritDoc} */ > public void setupFontInfo(IFDocumentHandler documentHandler, FontInfo fontInfo) >- throws FOPException { >+ throws FOPException { > FontManager fontManager = userAgent.getFactory().getFontManager(); > List fontCollections = new java.util.ArrayList(); > >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/modca/MapCodedFont.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/modca/MapCodedFont.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/modca/MapCodedFont.java (working copy) >@@ -29,6 +29,7 @@ > import org.apache.fop.afp.AFPConstants; > import org.apache.fop.afp.fonts.AFPFont; > import org.apache.fop.afp.fonts.CharacterSet; >+import org.apache.fop.afp.fonts.DoubleByteFont; > import org.apache.fop.afp.fonts.FontRuntimeException; > import org.apache.fop.afp.fonts.OutlineFont; > import org.apache.fop.afp.fonts.RasterFont; >@@ -217,6 +218,24 @@ > AFPConstants.EBCIDIC_ENCODING) > + " must have a fixed length of 8 characters."); > } >+ } else if (font instanceof DoubleByteFont) { >+ DoubleByteFont outline = (DoubleByteFont) font; >+ CharacterSet cs = outline.getCharacterSet(); >+ fontDefinition.characterSet = cs.getNameBytes(); >+ >+ // There are approximately 72 points to 1 inch or 20 1440ths per point. >+ >+ fontDefinition.scale = 20 * size / 1000; >+ >+ fontDefinition.codePage = cs.getCodePage().getBytes( >+ AFPConstants.EBCIDIC_ENCODING); >+ >+ if (fontDefinition.codePage.length != 8) { >+ throw new IllegalArgumentException("The code page " >+ + new String(fontDefinition.codePage, >+ AFPConstants.EBCIDIC_ENCODING) >+ + " must have a fixed length of 8 characters."); >+ } > } else { > String msg = "Font of type " + font.getClass().getName() > + " not recognized."; >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/OutlineFont.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/OutlineFont.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/OutlineFont.java (working copy) >@@ -21,163 +21,17 @@ > > > /** >- * A font defined as a set of lines and curves as opposed to a bitmap font. An >- * outline font can be scaled to any size and otherwise transformed more easily >- * than a bitmap font, and with more attractive results. <p/> >+ * Default implementation of AbstractOutlineFont. > * > */ >-public class OutlineFont extends AFPFont { >+public class OutlineFont extends AbstractOutlineFont { > >- /** The character set for this font */ >- private CharacterSet charSet = null; >- >- /** >- * Constructor for an outline font. >- * >- * @param name >- * the name of the font >- * @param charSet >- * the chracter set >- */ >+ /** {@inheritDoc} */ > public OutlineFont(String name, CharacterSet charSet) { >- super(name); >- this.charSet = charSet; >- } >+ super(name, charSet); > >- /** >- * Get the character set metrics. >- * >- * @return the character set >- */ >- public CharacterSet getCharacterSet() { >- >- return charSet; >- > } > >- /** >- * Get the character set metrics. >- * @param size ignored >- * @return the character set >- */ >- public CharacterSet getCharacterSet(int size) { > >- return charSet; > >- } >- >- /** >- * Get the first character in this font. >- * @return the first character in this font >- */ >- public int getFirstChar() { >- return charSet.getFirstChar(); >- } >- >- /** >- * Get the last character in this font. >- * @return the last character in this font >- */ >- public int getLastChar() { >- return charSet.getLastChar(); >- } >- >- /** >- * The ascender is the part of a lowercase letter that extends above the >- * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also >- * used to denote the part of the letter extending above the x-height. >- * >- * @param size the font size (in mpt) >- * @return the ascender for the given size >- */ >- public int getAscender(int size) { >- return charSet.getAscender() * size; >- } >- >- /** >- * Obtains the height of capital letters for the specified point size. >- * >- * @param size the font size (in mpt) >- * @return the cap height for the given size >- */ >- public int getCapHeight(int size) { >- return charSet.getCapHeight() * size; >- } >- >- /** >- * The descender is the part of a lowercase letter that extends below the >- * base line, such as "g", "j", or "p". Also used to denote the part of the >- * letter extending below the base line. >- * >- * @param size the font size (in mpt) >- * @return the descender for the given size >- */ >- public int getDescender(int size) { >- return charSet.getDescender() * size; >- } >- >- /** >- * The "x-height" (the height of the letter "x"). >- * >- * @param size the font size (in mpt) >- * @return the x height for the given size >- */ >- public int getXHeight(int size) { >- return charSet.getXHeight() * size; >- } >- >- /** >- * Obtain the width of the character for the specified point size. >- * @param character the character >- * @param size the font size (in mpt) >- * @return the width of the character for the specified point size >- */ >- public int getWidth(int character, int size) { >- return charSet.getWidth(character) * size; >- } >- >- /** >- * Get the getWidth (in 1/1000ths of a point size) of all characters in this >- * character set. >- * >- * @param size the font size (in mpt) >- * @return the widths of all characters >- */ >- public int[] getWidths(int size) { >- int[] widths = charSet.getWidths(); >- for (int i = 0; i < widths.length; i++) { >- widths[i] = widths[i] * size; >- } >- return widths; >- } >- >- /** >- * Get the getWidth (in 1/1000ths of a point size) of all characters in this >- * character set. >- * >- * @return the widths of all characters >- */ >- public int[] getWidths() { >- return getWidths(1000); >- } >- >- /** {@inheritDoc} */ >- public boolean hasChar(char c) { >- return charSet.hasChar(c); >- } >- >- /** >- * Map a Unicode character to a code point in the font. >- * @param c character to map >- * @return the mapped character >- */ >- public char mapChar(char c) { >- return charSet.mapChar(c); >- } >- >- /** {@inheritDoc} */ >- public String getEncodingName() { >- return charSet.getEncoding(); >- } >- > } >\ No newline at end of file >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSet.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSet.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSet.java (working copy) >@@ -20,7 +20,6 @@ > package org.apache.fop.afp.fonts; > > import java.io.File; >-import java.io.IOException; > import java.io.UnsupportedEncodingException; > import java.net.URI; > import java.nio.ByteBuffer; >@@ -60,7 +59,7 @@ > public class CharacterSet { > > /** Static logging instance */ >- protected static final Log log = LogFactory.getLog(CharacterSet.class.getName()); >+ protected static final Log LOG = LogFactory.getLog(CharacterSet.class.getName()); > > /** default codepage */ > public static final String DEFAULT_CODEPAGE = "T1V10500"; >@@ -122,11 +121,11 @@ > * @param name the character set name > * @param accessor the resource accessor to load resource with > */ >- public CharacterSet(String codePage, String encoding, String name, ResourceAccessor accessor) { >+ CharacterSet(String codePage, String encoding, String name, ResourceAccessor accessor) { > if (name.length() > MAX_NAME_LEN) { > String msg = "Character set name '" + name + "' must be a maximum of " > + MAX_NAME_LEN + " characters"; >- log.error("Constructor:: " + msg); >+ LOG.error("Constructor:: " + msg); > throw new IllegalArgumentException(msg); > } > >@@ -192,7 +191,7 @@ > * @return the ascender value in millipoints > */ > public int getAscender() { >- load(); >+ > return getCharacterSetOrientation().getAscender(); > } > >@@ -204,7 +203,7 @@ > * @return the cap height value in millipoints > */ > public int getCapHeight() { >- load(); >+ > return getCharacterSetOrientation().getCapHeight(); > } > >@@ -216,7 +215,7 @@ > * @return the descender value in millipoints > */ > public int getDescender() { >- load(); >+ > return getCharacterSetOrientation().getDescender(); > } > >@@ -226,7 +225,7 @@ > * @return the first character in the character set > */ > public int getFirstChar() { >- load(); >+ > return getCharacterSetOrientation().getFirstChar(); > } > >@@ -236,7 +235,7 @@ > * @return the last character in the character set > */ > public int getLastChar() { >- load(); >+ > return getCharacterSetOrientation().getLastChar(); > } > >@@ -254,7 +253,7 @@ > * @return the widths of all characters > */ > public int[] getWidths() { >- load(); >+ > return getCharacterSetOrientation().getWidths(); > } > >@@ -264,7 +263,7 @@ > * @return the typical height of characters > */ > public int getXHeight() { >- load(); >+ > return getCharacterSetOrientation().getXHeight(); > } > >@@ -276,28 +275,12 @@ > * @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 > * >@@ -318,7 +301,7 @@ > nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); > } catch (UnsupportedEncodingException usee) { > nameBytes = name.getBytes(); >- log.warn( >+ LOG.warn( > "UnsupportedEncodingException translating the name " + name); > } > return nameBytes; >@@ -417,4 +400,13 @@ > return c; > } > >+ /** >+ * >+ * @return the number units per em >+ */ >+ public int getEmSpaceIncrement() { >+ >+ return getCharacterSetOrientation().getUnitsPerEm(); >+ } >+ > } >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java (working copy) >@@ -33,10 +33,15 @@ > import org.apache.fop.afp.AFPConstants; > import org.apache.fop.afp.util.ResourceAccessor; > import org.apache.fop.afp.util.StructuredFieldReader; >+import org.apache.fop.fonts.Typeface; > > /** >- * 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 >+ * The CharacterSetBuilder is responsible building the a CharacterSet instance that holds >+ * the font metric data. The data is either read from disk and passed to a CharacterSet (*) >+ * or a FopCharacterSet is instantiated that is composed of a Typeface instance configured >+ * with this data.<p/> >+ * -*- For referenced fonts CharacterSetBuilder 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 >@@ -49,14 +54,13 @@ > * 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 { >+public class CharacterSetBuilder { > > /** > * Static logging instance > */ >- protected static final Log log = LogFactory.getLog(AFPFontReader.class); >+ protected static final Log LOG = LogFactory.getLog(CharacterSetBuilder.class); > > /** > * Template used to convert lists to arrays. >@@ -97,16 +101,36 @@ > private final Map/*<String, Map<String, String>>*/ codePagesCache > = new java.util.HashMap/*<String, Map<String, String>>*/(); > >+ >+ private CharacterSetBuilder() { } >+ > /** >+ * Factory method for the single-byte implementation of AFPFontReader. >+ * @return AFPFontReader >+ */ >+ public static CharacterSetBuilder getInstance() { >+ return new CharacterSetBuilder(); >+ } >+ >+ /** >+ * Factory method for the double-byte (CID Keyed font (Type 0)) implementation of AFPFontReader. >+ * @return AFPFontReader >+ */ >+ public static CharacterSetBuilder getDoubleByteInstance() { >+ return new DoubleByteLoader(); >+ } >+ >+ >+ /** > * Returns an InputStream to a given file path and filename > * >- * @param path the file path >+ * * @param accessor the resource accessor > * @param filename the file name > * @return an inputStream > * > * @throws IOException in the event that an I/O exception of some sort has occurred > */ >- private InputStream openInputStream(ResourceAccessor accessor, String filename) >+ protected InputStream openInputStream(ResourceAccessor accessor, String filename) > throws IOException { > URI uri; > try { >@@ -124,14 +148,14 @@ > * > * @param inputStream the inputstream to close > */ >- private void closeInputStream(InputStream inputStream) { >+ protected void closeInputStream(InputStream inputStream) { > try { > if (inputStream != null) { > inputStream.close(); > } > } catch (Exception ex) { > // Lets log at least! >- log.error(ex.getMessage()); >+ LOG.error(ex.getMessage()); > } > } > >@@ -139,12 +163,16 @@ > * 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. >+ * @param codePageName name of the code page file >+ * @param encoding >+ * @throws RuntimeException if an I/O exception of some sort has occurred. > */ >- public void loadCharacterSetMetric(CharacterSet characterSet) throws IOException { >+ public CharacterSet build(String characterSetName, String codePageName, >+ String encoding, ResourceAccessor accessor) { > >+ CharacterSet characterSet = new CharacterSet( >+ codePageName, encoding, characterSetName, accessor); >+ > InputStream inputStream = null; > > try { >@@ -154,24 +182,18 @@ > * information to map the unicode character id to the graphic > * chracter global identifier. > */ >- String codePageId = new String(characterSet.getCodePage()); >- ResourceAccessor accessor = characterSet.getResourceAccessor(); > >+ > Map/*<String,String>*/ codePage >- = (Map/*<String,String>*/)codePagesCache.get(codePageId); >+ = (Map/*<String,String>*/)codePagesCache.get(codePageName); > > if (codePage == null) { >- codePage = loadCodePage(codePageId, characterSet.getEncoding(), accessor); >- codePagesCache.put(codePageId, codePage); >+ codePage = loadCodePage(codePageName, encoding, accessor); >+ codePagesCache.put(codePageName, 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(accessor, characterSetName); > > StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); >@@ -208,18 +230,45 @@ > characterSet.addCharacterSetOrientation(characterSetOrientations[i]); > } > } else { >- throw new IOException( >- "Failed to read font control structured field in character set " >- + characterSetName); >+ >+ String msg = "Failed to load the character set metrics for code page " >+ + codePageName; >+ LOG.error(msg); >+ throw new RuntimeException("Failed to read font control structured field" >+ + "in character set " + characterSetName); >+ > } > >- } finally { >+ } catch(IOException e){ >+ String msg = "Failed to load the character set metrics for code page " + codePageName; >+ LOG.error(msg); >+ throw new RuntimeException("Failed to read font control structured field" >+ + "in character set " + characterSetName); >+ } >+ finally { >+ > closeInputStream(inputStream); > } > >+ return characterSet; >+ > } > > /** >+ * 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 CharacterSet build(String characterSetName, String codePageName, >+ String encoding, Typeface typeface) { >+ return new FopCharacterSet(codePageName, encoding, characterSetName, typeface); >+ } >+ >+ >+ >+ /** > * 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'. > * >@@ -229,8 +278,9 @@ > * the encoding to use for the character decoding > * @param accessor the resource accessor > * @returns a code page mapping >+ * @throws IOException if an I/O exception of some sort has occurred. > */ >- private Map/*<String,String>*/ loadCodePage(String codePage, String encoding, >+ protected Map/*<String,String>*/ loadCodePage(String codePage, String encoding, > ResourceAccessor accessor) throws IOException { > > // Create the HashMap to store code page information >@@ -277,8 +327,10 @@ > * > * @param structuredFieldReader the structured field reader > * @return a class representing the font descriptor >+ * @throws IOException if an I/O exception of some sort has occurred. > */ >- private static FontDescriptor processFontDescriptor(StructuredFieldReader structuredFieldReader) >+ protected static FontDescriptor processFontDescriptor( >+ StructuredFieldReader structuredFieldReader) > throws IOException { > > byte[] fndData = structuredFieldReader.getNext(FONT_DESCRIPTOR_SF); >@@ -290,8 +342,10 @@ > * > * @param structuredFieldReader > * the structured field reader >+ * @return the FontControl >+ * @throws IOException if an I/O exception of some sort has occurred. > */ >- private FontControl processFontControl(StructuredFieldReader structuredFieldReader) >+ protected FontControl processFontControl(StructuredFieldReader structuredFieldReader) > throws IOException { > > byte[] fncData = structuredFieldReader.getNext(FONT_CONTROL_SF); >@@ -320,8 +374,10 @@ > * > * @param structuredFieldReader > * the structured field reader >+ * @return CharacterSetOrientation array >+ * @throws IOException if an I/O exception of some sort has occurred. > */ >- private CharacterSetOrientation[] processFontOrientation( >+ protected CharacterSetOrientation[] processFontOrientation( > StructuredFieldReader structuredFieldReader) throws IOException { > > byte[] data = structuredFieldReader.getNext(FONT_ORIENTATION_SF); >@@ -381,8 +437,9 @@ > * the array of CharacterSetOrientation objects > * @param metricNormalizationFactor factor to apply to the metrics to get normalized > * font metric values >+ * @throws IOException if an I/O exception of some sort has occurred. > */ >- private void processFontPosition(StructuredFieldReader structuredFieldReader, >+ protected void processFontPosition(StructuredFieldReader structuredFieldReader, > CharacterSetOrientation[] characterSetOrientations, double metricNormalizationFactor) > throws IOException { > >@@ -437,8 +494,9 @@ > * @param codepage the map of code pages > * @param metricNormalizationFactor factor to apply to the metrics to get normalized > * font metric values >+ * @throws IOException if an I/O exception of some sort has occurred. > */ >- private void processFontIndex(StructuredFieldReader structuredFieldReader, >+ protected void processFontIndex(StructuredFieldReader structuredFieldReader, > CharacterSetOrientation cso, Map/*<String,String>*/ codepage, > double metricNormalizationFactor) > throws IOException { >@@ -485,8 +543,8 @@ > double diffPercent = 100 * diff / (double)width; > //if difference > 2% > if (diffPercent > 2) { >- if (log.isTraceEnabled()) { >- log.trace(gcgiString + ": " >+ if (LOG.isTraceEnabled()) { >+ LOG.trace(gcgiString + ": " > + a + " + " + b + " + " + c + " = " + (a + b + c) > + " but found: " + width); > } >@@ -516,9 +574,9 @@ > cso.setFirstChar(lowest); > cso.setLastChar(highest); > >- if (log.isDebugEnabled() && firstABCMismatch != null) { >+ if (LOG.isDebugEnabled() && firstABCMismatch != null) { > //Debug level because it usually is no problem. >- log.debug("Font has metrics inconsitencies where A+B+C doesn't equal the" >+ LOG.debug("Font has metrics inconsitencies where A+B+C doesn't equal the" > + " character increment. The first such character found: " > + firstABCMismatch); > } >@@ -584,4 +642,115 @@ > } > } > >+ /** >+ * Double-byte (CID Keyed font (Type 0)) implementation of AFPFontReader. >+ */ >+ private static class DoubleByteLoader extends CharacterSetBuilder { >+ >+ protected Map/*<String,String>*/ loadCodePage(String codePage, String encoding, >+ ResourceAccessor accessor) 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(accessor, codePage.trim()); >+ >+ StructuredFieldReader structuredFieldReader >+ = new StructuredFieldReader(inputStream); >+ byte[] data; // = structuredFieldReader.getNext(CHARACTER_TABLE_SF); >+ while ((data = structuredFieldReader.getNext(CHARACTER_TABLE_SF)) != null) { >+ int position = 0; >+ >+ byte[] gcgiBytes = new byte[8]; >+ byte[] charBytes = new byte[2]; >+ // Read data, ignoring bytes 0 - 2 >+ for (int index = 3; index < data.length; index++) { >+ >+ if (position < 8) { >+ // Build the graphic character global identifier key >+ gcgiBytes[position] = data[index]; >+ position++; >+ } else if (position == 9) { >+ // Set the character >+ charBytes[0] = data[index]; >+ position++; >+ } else if (position == 10) { >+ position = 0; >+ // Set the character >+ charBytes[1] = data[index]; >+ >+ String gcgiString = new String(gcgiBytes, >+ AFPConstants.EBCIDIC_ENCODING); >+ String charString = new String(charBytes, encoding); >+ codePages.put(gcgiString, charString); >+ >+ } >+ else { >+ position++; >+ } >+ } >+ } >+ } finally { >+ closeInputStream(inputStream); >+ } >+ >+ return codePages; >+ } >+ >+ protected CharacterSetOrientation[] processFontOrientation( >+ StructuredFieldReader structuredFieldReader) throws IOException { >+ >+ byte[] data = structuredFieldReader.getNext(FONT_ORIENTATION_SF); >+ >+ int position = 0; >+ byte[] fnoData = new byte[26]; >+ >+ List orientations = new java.util.ArrayList(); >+ >+ // Read data, ignoring bytes 0 - 2 >+ for (int index = 3; index < data.length; index++) { >+ // Build the font orientation record >+ fnoData[position] = data[index]; >+ position++; >+ >+ if (position == 26) { >+ >+ position = 0; >+ >+ int orientation = 0; >+ >+ switch (fnoData[2]) { >+ case 0x00: >+ orientation = 0; >+ break; >+ case 0x2D: >+ orientation = 90; >+ break; >+ case 0x5A: >+ orientation = 180; >+ break; >+ case (byte) 0x87: >+ orientation = 270; >+ break; >+ default: >+ System.out.println("ERROR: Oriantation"); >+ } >+ >+ // Em-Space Increment >+ int em = ((fnoData[14] & 0xFF ) << 8) + (fnoData[15] & 0xFF); >+ >+ CharacterSetOrientation cso = new CharacterSetOrientation( >+ orientation, em); >+ orientations.add(cso); >+ >+ } >+ } >+ >+ return (CharacterSetOrientation[]) orientations >+ .toArray(EMPTY_CSO_ARRAY); >+ } >+ } >+ > } >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/AFPFontReader.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/AFPFontReader.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/AFPFontReader.java (working copy) >@@ -1,587 +0,0 @@ >-/* >- * 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.FileNotFoundException; >-import java.io.IOException; >-import java.io.InputStream; >-import java.net.URI; >-import java.net.URISyntaxException; >-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.ResourceAccessor; >-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(AFPFontReader.class); >- >- /** >- * 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 descriptor MO:DCA structured field. */ >- private static final byte[] FONT_DESCRIPTOR_SF = new byte[] { >- (byte) 0xD3, (byte) 0xA6, (byte) 0x89 }; >- >- /** 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 collection of code pages >- */ >- private final Map/*<String, Map<String, String>>*/ codePagesCache >- = 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(ResourceAccessor accessor, String filename) >- throws IOException { >- URI uri; >- try { >- uri = new URI(filename.trim()); >- } catch (URISyntaxException e) { >- throw new FileNotFoundException("Invalid filename: " >- + filename + " (" + e.getMessage() + ")"); >- } >- InputStream inputStream = accessor.createInputStream(uri); >- 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()); >- ResourceAccessor accessor = characterSet.getResourceAccessor(); >- >- Map/*<String,String>*/ codePage >- = (Map/*<String,String>*/)codePagesCache.get(codePageId); >- >- if (codePage == null) { >- codePage = loadCodePage(codePageId, characterSet.getEncoding(), accessor); >- codePagesCache.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(accessor, characterSetName); >- >- StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); >- >- // Process D3A689 Font Descriptor >- FontDescriptor fontDescriptor = processFontDescriptor(structuredFieldReader); >- characterSet.setNominalVerticalSize(fontDescriptor.getNominalFontSizeInMillipoints()); >- >- // Process D3A789 Font Control >- FontControl fontControl = processFontControl(structuredFieldReader); >- >- if (fontControl != null) { >- //process D3AE89 Font Orientation >- CharacterSetOrientation[] characterSetOrientations >- = processFontOrientation(structuredFieldReader); >- >- int metricNormalizationFactor; >- if (fontControl.isRelative()) { >- metricNormalizationFactor = 1; >- } else { >- int dpi = fontControl.getDpi(); >- metricNormalizationFactor = 1000 * 72000 >- / fontDescriptor.getNominalFontSizeInMillipoints() / dpi; >- } >- >- //process D3AC89 Font Position >- processFontPosition(structuredFieldReader, characterSetOrientations, >- metricNormalizationFactor); >- >- //process D38C89 Font Index (per orientation) >- for (int i = 0; i < characterSetOrientations.length; i++) { >- processFontIndex(structuredFieldReader, >- characterSetOrientations[i], codePage, metricNormalizationFactor); >- 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 >- * @param accessor the resource accessor >- * @returns a code page mapping >- */ >- private Map/*<String,String>*/ loadCodePage(String codePage, String encoding, >- ResourceAccessor accessor) 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(accessor, 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); >- codePages.put(gcgiString, charString); >- } else { >- position++; >- } >- } >- } finally { >- closeInputStream(inputStream); >- } >- >- return codePages; >- } >- >- /** >- * Process the font descriptor details using the structured field reader. >- * >- * @param structuredFieldReader the structured field reader >- * @return a class representing the font descriptor >- */ >- private static FontDescriptor processFontDescriptor(StructuredFieldReader structuredFieldReader) >- throws IOException { >- >- byte[] fndData = structuredFieldReader.getNext(FONT_DESCRIPTOR_SF); >- return new FontDescriptor(fndData); >- } >- >- /** >- * 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); >- >- FontControl fontControl = null; >- if (fncData != null) { >- fontControl = new FontControl(); >- >- if (fncData[7] == (byte) 0x02) { >- fontControl.setRelative(true); >- } >- int metricResolution = getUBIN(fncData, 9); >- if (metricResolution == 1000) { >- //Special case: 1000 units per em (rather than dpi) >- fontControl.setUnitsPerEm(1000); >- } else { >- fontControl.setDpi(metricResolution / 10); >- } >- } >- 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 >- * @param metricNormalizationFactor factor to apply to the metrics to get normalized >- * font metric values >- */ >- private void processFontPosition(StructuredFieldReader structuredFieldReader, >- CharacterSetOrientation[] characterSetOrientations, double metricNormalizationFactor) >- throws IOException { >- >- byte[] data = structuredFieldReader.getNext(FONT_POSITION_SF); >- >- int position = 0; >- byte[] fpData = new byte[26]; >- >- int characterSetOrientationIndex = 0; >- >- // 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]; >- if (position == 9) { >- CharacterSetOrientation characterSetOrientation >- = characterSetOrientations[characterSetOrientationIndex]; >- >- int xHeight = getSBIN(fpData, 2); >- int capHeight = getSBIN(fpData, 4); >- int ascHeight = getSBIN(fpData, 6); >- int dscHeight = getSBIN(fpData, 8); >- >- dscHeight = dscHeight * -1; >- >- characterSetOrientation.setXHeight( >- (int)Math.round(xHeight * metricNormalizationFactor)); >- characterSetOrientation.setCapHeight( >- (int)Math.round(capHeight * metricNormalizationFactor)); >- characterSetOrientation.setAscender( >- (int)Math.round(ascHeight * metricNormalizationFactor)); >- characterSetOrientation.setDescender( >- (int)Math.round(dscHeight * metricNormalizationFactor)); >- } >- } else if (position == 22) { >- position = 0; >- 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 >- * @param metricNormalizationFactor factor to apply to the metrics to get normalized >- * font metric values >- */ >- private void processFontIndex(StructuredFieldReader structuredFieldReader, >- CharacterSetOrientation cso, Map/*<String,String>*/ codepage, >- double metricNormalizationFactor) >- throws IOException { >- >- byte[] data = structuredFieldReader.getNext(FONT_INDEX_SF); >- >- int position = 0; >- >- byte[] gcgid = new byte[8]; >- byte[] fiData = new byte[20]; >- >- int lowest = 255; >- int highest = 0; >- String firstABCMismatch = null; >- >- // 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 = getUBIN(fiData, 0); >- int a = getSBIN(fiData, 10); >- int b = getUBIN(fiData, 12); >- int c = getSBIN(fiData, 14); >- int abc = a + b + c; >- int diff = Math.abs(abc - width); >- if (diff != 0 && width != 0) { >- double diffPercent = 100 * diff / (double)width; >- //if difference > 2% >- if (diffPercent > 2) { >- if (log.isTraceEnabled()) { >- log.trace(gcgiString + ": " >- + a + " + " + b + " + " + c + " = " + (a + b + c) >- + " but found: " + width); >- } >- if (firstABCMismatch == null) { >- firstABCMismatch = gcgiString; >- } >- } >- } >- >- if (cidx < lowest) { >- lowest = cidx; >- } >- >- if (cidx > highest) { >- highest = cidx; >- } >- >- int normalizedWidth = (int)Math.round(width * metricNormalizationFactor); >- >- cso.setWidth(cidx, normalizedWidth); >- >- } >- >- } >- } >- >- cso.setFirstChar(lowest); >- cso.setLastChar(highest); >- >- if (log.isDebugEnabled() && firstABCMismatch != null) { >- //Debug level because it usually is no problem. >- log.debug("Font has metrics inconsitencies where A+B+C doesn't equal the" >- + " character increment. The first such character found: " >- + firstABCMismatch); >- } >- } >- >- private static int getUBIN(byte[] data, int start) { >- return ((data[start] & 0xFF) << 8) + (data[start + 1] & 0xFF); >- } >- >- private static int getSBIN(byte[] data, int start) { >- int ubin = ((data[start] & 0xFF) << 8) + (data[start + 1] & 0xFF); >- if ((ubin & 0x8000) != 0) { >- //extend sign >- return ubin | 0xFFFF0000; >- } else { >- return ubin; >- } >- } >- >- private class FontControl { >- >- private int dpi; >- private int unitsPerEm; >- >- private boolean isRelative = false; >- >- public int getDpi() { >- return dpi; >- } >- >- public void setDpi(int i) { >- dpi = i; >- } >- >- public int getUnitsPerEm() { >- return this.unitsPerEm; >- } >- >- public void setUnitsPerEm(int value) { >- this.unitsPerEm = value; >- } >- >- public boolean isRelative() { >- return isRelative; >- } >- >- public void setRelative(boolean b) { >- isRelative = b; >- } >- } >- >- private static class FontDescriptor { >- >- private byte[] data; >- >- public FontDescriptor(byte[] data) { >- this.data = data; >- } >- >- public int getNominalFontSizeInMillipoints() { >- int nominalFontSize = 100 * getUBIN(data, 39); >- return nominalFontSize; >- } >- } >- >-} >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java (revision 900314) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java (working copy) >@@ -19,6 +19,8 @@ > > package org.apache.fop.afp.fonts; > >+import java.util.Arrays; >+ > /** > * The IBM Font Object Content Architecture (FOCA) supports presentation > * of character shapes by defining their characteristics, which include >@@ -58,7 +60,7 @@ > /** > * The character widths in the character set > */ >- private int[] charsWidths = new int[256]; >+ private int[] charsWidths = null; > > /** > * The height of lowercase letters >@@ -82,15 +84,33 @@ > private int orientation = 0; > > /** >+ * Units per em >+ */ >+ private int unitsPerEm = -1; >+ /** > * Constructor for the CharacterSetOrientation, the orientation is > * expressed as the degrees rotation (i.e 0, 90, 180, 270) > * @param orientation the character set orientation > */ > public CharacterSetOrientation(int orientation) { > this.orientation = orientation; >+ charsWidths = new int[256]; >+ Arrays.fill(charsWidths, -1); > } > > /** >+ * Constructor for the CharacterSetOrientation, the orientation is >+ * expressed as the degrees rotation (i.e 0, 90, 180, 270) >+ * @param orientation the character set orientation >+ * @param unitsPerEm the units per em >+ */ >+ public CharacterSetOrientation(int orientation, int unitsPerEm) { >+ this(orientation); >+ this.unitsPerEm = unitsPerEm; >+ >+ } >+ >+ /** > * Ascender height is the distance from the character baseline to the > * top of the character box. A negative ascender height signifies that > * all of the graphic character is below the character baseline. For >@@ -245,8 +265,10 @@ > public void setWidth(int character, int width) { > if (character >= charsWidths.length) { > // Increase the size of the array if necessary >+ // TODO Can we remove firstChar? surely firstChar==0 at this stage? > int[] arr = new int[(character - firstChar) + 1]; > System.arraycopy(charsWidths, 0, arr, 0, charsWidths.length); >+ Arrays.fill(arr, charsWidths.length, character - firstChar, -1); > charsWidths = arr; > } > charsWidths[character] = width; >@@ -261,4 +283,13 @@ > public void setXHeight(int xHeight) { > this.xHeight = xHeight; > } >+ >+ /** >+ * >+ * @return units per em >+ */ >+ >+ public int getUnitsPerEm(){ >+ return this.unitsPerEm; >+ } > } >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java (revision 0) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java (revision 0) >@@ -0,0 +1,178 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id: OutlineFont.java 791781 2009-07-07 10:21:07Z cbowditch $ */ >+ >+package org.apache.fop.afp.fonts; >+ >+import java.util.HashSet; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+ >+ >+/** >+ * Implementation of AbstractOutlineFont that supports double-byte fonts (CID Keyed font (Type 0)). >+ * The width of characters that are not prescribed a width metrics in the font resource use >+ * a fallback width. The default width is 1 em. A character can be supplied and queried for the >+ * fallback width of all non-ideograph characters.<p /> >+ */ >+public class DoubleByteFont extends AbstractOutlineFont { >+ >+ private static final Log LOG = LogFactory.getLog(DoubleByteFont.class); >+ >+ private static final HashSet IDEOGRAPHIC = new HashSet(); >+ static { >+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS); >+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT); >+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS); >+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A); >+ IDEOGRAPHIC.add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B); >+ } >+ >+ /* The fallback character is used for assigning width metrics to characters >+ with no mapped width in font resource*/ >+ private int fallbackChar; >+ >+ // lazy assigned fallbackCharWidth >+ private int fallbackCharWidth = -1; // -1 to code for not assigned >+ // lazy assigned emWidth >+ private int emWidth = -1; // -1 to code for not assigned >+ // use em as fallback width >+ private boolean isFallbackEmWidth = true; >+ >+ >+ /** >+ * Constructor for an double-byte outline font. >+ * >+ * @param name >+ * the name of the font >+ * @param charSet >+ * the character set >+ >+ */ >+ public DoubleByteFont(String name, CharacterSet charSet) { >+ super(name, charSet); >+ >+ } >+ >+ /** >+ * Constructor for an outline font. >+ * >+ * @param name >+ * the name of the font >+ * @param charSet >+ * the character set >+ * @param fallbackCharacter >+ * fallback character for assigning width metrics to characters >+ * with no mapped width in font resource >+ */ >+ public DoubleByteFont(String name, CharacterSet charSet, int fallbackCharacter) { >+ super(name, charSet); >+ this.fallbackChar = fallbackCharacter; >+ this.isFallbackEmWidth = false; >+ } >+ >+ >+ >+ >+ /** {@inheritDoc} */ >+ public int getWidth(int character, int size) { >+ int charWidth; >+ try { >+ charWidth = charSet.getWidth(character); >+ } catch (IllegalArgumentException e) { >+ // We shall try and handle characters that have no mapped width metric in font resource >+ charWidth = -1; >+ } >+ >+ if (charWidth == -1) { >+ charWidth = inferCharWidth(character); >+ } >+ return charWidth * size; >+ } >+ >+ >+ >+ private int inferCharWidth(int character) { >+ >+ //Is this character an ideograph? >+ boolean isIdeographic = false; >+ Character.UnicodeBlock charBlock = Character.UnicodeBlock.of(character); >+ if (charBlock == null) { >+ isIdeographic = false; >+ } else if (IDEOGRAPHIC.contains(charBlock)) { >+ isIdeographic = true; >+ } else { //default >+ isIdeographic = false; >+ } >+ >+ return isIdeographic ? getEmWidth() : getFallbackWidth(); >+ } >+ >+ >+ private int getEmWidth() { >+ >+ if (emWidth == -1) { >+ >+ int width = charSet.getEmSpaceIncrement(); >+ >+ LOG.debug("em is " + width); >+ >+ if (width == -1) { >+ LOG.warn("Could not determine 'em' of font " + name >+ + ".\n\tUsing the fallback width instead.)"); >+ width = 0; >+ } >+ emWidth = width; >+ } >+ >+ return emWidth; >+ >+ } >+ >+ private int getFallbackWidth() { >+ //We shall cache the width in fallbackCharWidth >+ >+ if (isFallbackEmWidth) { >+ return getEmWidth(); >+ } else { >+ if (fallbackCharWidth == -1) { >+ // cache the >+ try { >+ fallbackCharWidth = charSet.getWidth(fallbackChar); >+ >+ if (fallbackCharWidth == -1) { >+ LOG.warn("No width metric found for the FALLBACK character (codepoint=" >+ + fallbackChar + ") in font " + name); >+ fallbackCharWidth = getEmWidth(); >+ } >+ } catch (IllegalArgumentException e) { >+ LOG.warn("No width metric found for the FALLBACK character (codepoint=" >+ + fallbackChar + ") in font " + name); >+ fallbackCharWidth = getEmWidth(); >+ } >+ LOG.warn("Fallback width of font " + name + " is " >+ + fallbackCharWidth + "*font-size"); >+ } >+ return fallbackCharWidth; >+ } >+ >+ } >+ >+ >+} >Index: /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java >=================================================================== >--- /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java (revision 0) >+++ /home/peter/fop_apache/fop_afpfonts/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java (revision 0) >@@ -0,0 +1,183 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id:$ */ >+ >+package org.apache.fop.afp.fonts; >+ >+ >+/** >+ * A font defined as a set of lines and curves as opposed to a bitmap font. An >+ * outline font can be scaled to any size and otherwise transformed more easily >+ * than a bitmap font, and with more attractive results. <p/> >+ * >+ */ >+public abstract class AbstractOutlineFont extends AFPFont { >+ >+ /** The character set for this font */ >+ protected CharacterSet charSet = null; >+ >+ /** >+ * Constructor for an outline font. >+ * >+ * @param name >+ * the name of the font >+ * @param charSet >+ * the chracter set >+ */ >+ public AbstractOutlineFont(String name, CharacterSet charSet) { >+ super(name); >+ this.charSet = charSet; >+ } >+ >+ /** >+ * Get the character set metrics. >+ * >+ * @return the character set >+ */ >+ public CharacterSet getCharacterSet() { >+ >+ return charSet; >+ >+ } >+ >+ /** >+ * Get the character set metrics. >+ * @param size ignored >+ * @return the character set >+ */ >+ public CharacterSet getCharacterSet(int size) { >+ >+ return charSet; >+ >+ } >+ >+ /** >+ * Get the first character in this font. >+ * @return the first character in this font >+ */ >+ public int getFirstChar() { >+ return charSet.getFirstChar(); >+ } >+ >+ /** >+ * Get the last character in this font. >+ * @return the last character in this font >+ */ >+ public int getLastChar() { >+ return charSet.getLastChar(); >+ } >+ >+ /** >+ * The ascender is the part of a lowercase letter that extends above the >+ * "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also >+ * used to denote the part of the letter extending above the x-height. >+ * >+ * @param size the font size (in mpt) >+ * @return the ascender for the given size >+ */ >+ public int getAscender(int size) { >+ return charSet.getAscender() * size; >+ } >+ >+ /** >+ * Obtains the height of capital letters for the specified point size. >+ * >+ * @param size the font size (in mpt) >+ * @return the cap height for the given size >+ */ >+ public int getCapHeight(int size) { >+ return charSet.getCapHeight() * size; >+ } >+ >+ /** >+ * The descender is the part of a lowercase letter that extends below the >+ * base line, such as "g", "j", or "p". Also used to denote the part of the >+ * letter extending below the base line. >+ * >+ * @param size the font size (in mpt) >+ * @return the descender for the given size >+ */ >+ public int getDescender(int size) { >+ return charSet.getDescender() * size; >+ } >+ >+ /** >+ * The "x-height" (the height of the letter "x"). >+ * >+ * @param size the font size (in mpt) >+ * @return the x height for the given size >+ */ >+ public int getXHeight(int size) { >+ return charSet.getXHeight() * size; >+ } >+ >+ /** >+ * Obtain the width of the character for the specified point size. >+ * @param character the character >+ * @param size the font size (in mpt) >+ * @return the width of the character for the specified point size >+ */ >+ public int getWidth(int character, int size) { >+ return charSet.getWidth(character) * size; >+ } >+ >+ /** >+ * Get the getWidth (in 1/1000ths of a point size) of all characters in this >+ * character set. >+ * >+ * @param size the font size (in mpt) >+ * @return the widths of all characters >+ */ >+ public int[] getWidths(int size) { >+ int[] widths = charSet.getWidths(); >+ for (int i = 0; i < widths.length; i++) { >+ widths[i] = widths[i] * size; >+ } >+ return widths; >+ } >+ >+ /** >+ * Get the getWidth (in 1/1000ths of a point size) of all characters in this >+ * character set. >+ * >+ * @return the widths of all characters >+ */ >+ public int[] getWidths() { >+ return getWidths(1000); >+ } >+ >+ /** {@inheritDoc} */ >+ public boolean hasChar(char c) { >+ return charSet.hasChar(c); >+ } >+ >+ /** >+ * Map a Unicode character to a code point in the font. >+ * @param c character to map >+ * @return the mapped character >+ */ >+ public char mapChar(char c) { >+ return charSet.mapChar(c); >+ } >+ >+ /** {@inheritDoc} */ >+ public String getEncodingName() { >+ return charSet.getEncoding(); >+ } >+ >+} >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 48567
:
24854
| 24857 |
24877