diff options
author | Chris Bowditch <cbowditch@apache.org> | 2009-07-07 10:21:07 +0000 |
---|---|---|
committer | Chris Bowditch <cbowditch@apache.org> | 2009-07-07 10:21:07 +0000 |
commit | de12561c093eaa980ee7b9a7aac862a5f8508309 (patch) | |
tree | 564834efcb4bdfbb71d64705b57eb1926b670540 | |
parent | 28ab50e140f682d13def8895f2e7755acb81e190 (diff) | |
download | xmlgraphics-fop-de12561c093eaa980ee7b9a7aac862a5f8508309.tar.gz xmlgraphics-fop-de12561c093eaa980ee7b9a7aac862a5f8508309.zip |
bug fix: fractional points sizes in AFP not working correctly together with fo:inline
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@791781 13f79535-47bb-0310-9956-ffa450edef68
6 files changed, 157 insertions, 50 deletions
diff --git a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java index e607bef5f..fd9b05304 100644 --- a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java +++ b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java @@ -49,7 +49,7 @@ public class AFPBase12FontCollection implements FontCollection { private void addCharacterSet(RasterFont font, String charsetName, Base14Font base14) { for (int i = 0; i < RASTER_SIZES.length; i++) { - int size = RASTER_SIZES[i]; + int size = RASTER_SIZES[i] * 1000; FopCharacterSet characterSet = new FopCharacterSet( CharacterSet.DEFAULT_CODEPAGE, CharacterSet.DEFAULT_ENCODING, charsetName + CHARSET_REF[i], base14); diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java index 4e6a03259..25ea15278 100644 --- a/src/java/org/apache/fop/afp/fonts/AFPFontReader.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java @@ -177,7 +177,8 @@ public final class AFPFontReader { StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); // Process D3A689 Font Descriptor - int pointSize = processFontDescriptor(structuredFieldReader); + FontDescriptor fontDescriptor = processFontDescriptor(structuredFieldReader); + characterSet.setNominalVerticalSize(fontDescriptor.getNominalFontSizeInMillipoints()); // Process D3A789 Font Control FontControl fontControl = processFontControl(structuredFieldReader); @@ -187,12 +188,13 @@ public final class AFPFontReader { CharacterSetOrientation[] characterSetOrientations = processFontOrientation(structuredFieldReader); - int dpi = fontControl.getDpi(); - int metricNormalizationFactor = 0; + int metricNormalizationFactor; if (fontControl.isRelative()) { metricNormalizationFactor = 1; } else { - metricNormalizationFactor = 72000 / dpi / pointSize; + int dpi = fontControl.getDpi(); + metricNormalizationFactor = 1000 * 72000 + / fontDescriptor.getNominalFontSizeInMillipoints() / dpi; } //process D3AC89 Font Position @@ -274,15 +276,13 @@ public final class AFPFontReader { * Process the font descriptor details using the structured field reader. * * @param structuredFieldReader the structured field reader - * @return the nominal size of the font (in points) + * @return a class representing the font descriptor */ - private static int processFontDescriptor(StructuredFieldReader structuredFieldReader) + private static FontDescriptor processFontDescriptor(StructuredFieldReader structuredFieldReader) throws IOException { byte[] fndData = structuredFieldReader.getNext(FONT_DESCRIPTOR_SF); - - int nominalPointSize = (((fndData[39] & 0xFF) << 8) + (fndData[40] & 0xFF)) / 10; - return nominalPointSize; + return new FontDescriptor(fndData); } /** @@ -303,8 +303,13 @@ public final class AFPFontReader { if (fncData[7] == (byte) 0x02) { fontControl.setRelative(true); } - int metricResolution = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10; - fontControl.setDpi(metricResolution); + 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; } @@ -378,7 +383,7 @@ public final class AFPFontReader { * font metric values */ private void processFontPosition(StructuredFieldReader structuredFieldReader, - CharacterSetOrientation[] characterSetOrientations, int metricNormalizationFactor) + CharacterSetOrientation[] characterSetOrientations, double metricNormalizationFactor) throws IOException { byte[] data = structuredFieldReader.getNext(FONT_POSITION_SF); @@ -397,17 +402,21 @@ public final class AFPFontReader { 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); + 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(xHeight * metricNormalizationFactor); - characterSetOrientation.setCapHeight(capHeight * metricNormalizationFactor); - characterSetOrientation.setAscender(ascHeight * metricNormalizationFactor); - characterSetOrientation.setDescender(dscHeight * metricNormalizationFactor); + 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; @@ -430,7 +439,8 @@ public final class AFPFontReader { * font metric values */ private void processFontIndex(StructuredFieldReader structuredFieldReader, - CharacterSetOrientation cso, Map/*<String,String>*/ codepage, int metricNormalizationFactor) + CharacterSetOrientation cso, Map/*<String,String>*/ codepage, + double metricNormalizationFactor) throws IOException { byte[] data = structuredFieldReader.getNext(FONT_INDEX_SF); @@ -442,6 +452,7 @@ public final class AFPFontReader { int lowest = 255; int highest = 0; + String firstABCMismatch = null; // Read data, ignoring bytes 0 - 2 for (int index = 3; index < data.length; index++) { @@ -464,7 +475,26 @@ public final class AFPFontReader { if (idx != null) { int cidx = idx.charAt(0); - int width = ((fiData[0] & 0xFF) << 8) + (fiData[1] & 0xFF); + 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; @@ -474,9 +504,9 @@ public final class AFPFontReader { highest = cidx; } - int a = (width * metricNormalizationFactor); + int normalizedWidth = (int)Math.round(width * metricNormalizationFactor); - cso.setWidth(cidx, a); + cso.setWidth(cidx, normalizedWidth); } @@ -486,11 +516,32 @@ public final class AFPFontReader { 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; @@ -502,6 +553,14 @@ public final class AFPFontReader { dpi = i; } + public int getUnitsPerEm() { + return this.unitsPerEm; + } + + public void setUnitsPerEm(int value) { + this.unitsPerEm = value; + } + public boolean isRelative() { return isRelative; } @@ -511,4 +570,18 @@ public final class AFPFontReader { } } + 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; + } + } + } diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index 9573506b3..48d5f4f30 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -95,6 +95,9 @@ public class CharacterSet { /** The collection of objects for each orientation */ private Map characterSetOrientations = null; + /** The nominal vertical size (in millipoints) for bitmap fonts. 0 for outline fonts. */ + private int nominalVerticalSize = 0; + /** * Constructor for the CharacterSetMetric object, the character set is used * to load the font information from the actual AFP font. @@ -159,6 +162,23 @@ public class CharacterSet { } /** + * Sets the nominal vertical size of the font in the case of bitmap fonts. + * @param nominalVerticalSize the nominal vertical size (in millipoints) + */ + public void setNominalVerticalSize(int nominalVerticalSize) { + this.nominalVerticalSize = nominalVerticalSize; + } + + /** + * Returns the nominal vertical size of the font in the case of bitmap fonts. For outline fonts, + * zero is returned, because these are scalable fonts. + * @return the nominal vertical size (in millipoints) for bitmap fonts, or 0 for outline fonts. + */ + public int getNominalVerticalSize() { + return this.nominalVerticalSize; + } + + /** * 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 diff --git a/src/java/org/apache/fop/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/afp/fonts/OutlineFont.java index b97d5f3ab..8dca69f9c 100644 --- a/src/java/org/apache/fop/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/afp/fonts/OutlineFont.java @@ -87,8 +87,7 @@ public class OutlineFont extends AFPFont { * "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 + * @param size the font size (in mpt) * @return the ascender for the given size */ public int getAscender(int size) { @@ -98,8 +97,7 @@ public class OutlineFont extends AFPFont { /** * Obtains the height of capital letters for the specified point size. * - * @param size - * the point size + * @param size the font size (in mpt) * @return the cap height for the given size */ public int getCapHeight(int size) { @@ -111,8 +109,7 @@ public class OutlineFont extends AFPFont { * 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 + * @param size the font size (in mpt) * @return the descender for the given size */ public int getDescender(int size) { @@ -122,8 +119,7 @@ public class OutlineFont extends AFPFont { /** * The "x-height" (the height of the letter "x"). * - * @param size - * the point size + * @param size the font size (in mpt) * @return the x height for the given size */ public int getXHeight(int size) { @@ -133,7 +129,7 @@ public class OutlineFont extends AFPFont { /** * Obtain the width of the character for the specified point size. * @param character the character - * @param size point size + * @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) { @@ -144,8 +140,7 @@ public class OutlineFont extends AFPFont { * Get the getWidth (in 1/1000ths of a point size) of all characters in this * character set. * - * @param size - * the point size + * @param size the font size (in mpt) * @return the widths of all characters */ public int[] getWidths(int size) { diff --git a/src/java/org/apache/fop/afp/fonts/RasterFont.java b/src/java/org/apache/fop/afp/fonts/RasterFont.java index 4ac450ba4..eaac7d6df 100644 --- a/src/java/org/apache/fop/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/afp/fonts/RasterFont.java @@ -19,10 +19,10 @@ package org.apache.fop.afp.fonts; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.SortedMap; -import java.util.HashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -163,26 +163,37 @@ public class RasterFont extends AFPFont { } + private int metricsToAbsoluteSize(CharacterSet cs, int value, int givenSize) { + int nominalVerticalSize = cs.getNominalVerticalSize(); + if (nominalVerticalSize != 0) { + return value * nominalVerticalSize; + } else { + return value * givenSize; + } + } + /** * 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 (in mpt) + * @param size the font size (in mpt) * @return the ascender for the given point size */ public int getAscender(int size) { - return getCharacterSet(size).getAscender() * size; + CharacterSet cs = getCharacterSet(size); + return metricsToAbsoluteSize(cs, cs.getAscender(), size); } /** * Obtains the height of capital letters for the specified point size. * - * @param size the point size (in mpt) + * @param size the font size (in mpt) * @return the cap height for the specified point size */ public int getCapHeight(int size) { - return getCharacterSet(size).getCapHeight() * size; + CharacterSet cs = getCharacterSet(size); + return metricsToAbsoluteSize(cs, cs.getCapHeight(), size); } /** @@ -190,42 +201,50 @@ public class RasterFont extends AFPFont { * 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 (in mpt) + * @param size the font size (in mpt) * @return the descender for the specified point size */ public int getDescender(int size) { - return getCharacterSet(size).getDescender() * size; + CharacterSet cs = getCharacterSet(size); + return metricsToAbsoluteSize(cs, cs.getDescender(), size); } /** * The "x-height" (the height of the letter "x"). * - * @param size the point size (in mpt) + * @param size the font size (in mpt) * @return the x height for the given point size */ public int getXHeight(int size) { - return getCharacterSet(size).getXHeight() * size; + CharacterSet cs = getCharacterSet(size); + return metricsToAbsoluteSize(cs, cs.getXHeight(), size); } /** * Obtain the width of the character for the specified point size. * @param character the character - * @param size the point size (in mpt) + * @param size the font size (in mpt) * @return the width for the given point size */ public int getWidth(int character, int size) { - return getCharacterSet(size).getWidth(character) * size; + CharacterSet cs = getCharacterSet(size); + return metricsToAbsoluteSize(cs, cs.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 (in mpt) + * @param size the font size (in mpt) * @return the widths of all characters */ public int[] getWidths(int size) { - return getCharacterSet(size).getWidths(); + CharacterSet cs = getCharacterSet(size); + int[] widths = cs.getWidths(); + for (int i = 0, c = widths.length; i < c; i++) { + widths[i] = metricsToAbsoluteSize(cs, widths[i], size); + } + return widths; } /** diff --git a/src/java/org/apache/fop/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/afp/modca/MapCodedFont.java index 54b4d1796..e732a8bb7 100644 --- a/src/java/org/apache/fop/afp/modca/MapCodedFont.java +++ b/src/java/org/apache/fop/afp/modca/MapCodedFont.java @@ -206,7 +206,7 @@ public class MapCodedFont extends AbstractStructuredObject { // There are approximately 72 points to 1 inch or 20 1440ths per point. - fontDefinition.scale = ((size / 1000) * 20); + fontDefinition.scale = 20 * size / 1000; fontDefinition.codePage = cs.getCodePage().getBytes( AFPConstants.EBCIDIC_ENCODING); |