aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Bowditch <cbowditch@apache.org>2009-07-07 10:21:07 +0000
committerChris Bowditch <cbowditch@apache.org>2009-07-07 10:21:07 +0000
commitde12561c093eaa980ee7b9a7aac862a5f8508309 (patch)
tree564834efcb4bdfbb71d64705b57eb1926b670540
parent28ab50e140f682d13def8895f2e7755acb81e190 (diff)
downloadxmlgraphics-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
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java2
-rw-r--r--src/java/org/apache/fop/afp/fonts/AFPFontReader.java121
-rw-r--r--src/java/org/apache/fop/afp/fonts/CharacterSet.java20
-rw-r--r--src/java/org/apache/fop/afp/fonts/OutlineFont.java17
-rw-r--r--src/java/org/apache/fop/afp/fonts/RasterFont.java45
-rw-r--r--src/java/org/apache/fop/afp/modca/MapCodedFont.java2
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);