From 35516dcedaffc643ae48349c280adcba172c57a2 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Fri, 24 Oct 2008 13:20:51 +0000 Subject: AFPFontReader a lot more robust now with less copy/pasted code but still far from ideal, the whole AFP FOCA parsing/handling still in need of a rewrite at some point. CharacterSetOrientation width() renamed to getWidth() and now protects itself against a possible ArrayIndexOutOfBoundsException. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@707627 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/Font.java | 11 +- src/java/org/apache/fop/fonts/FontSetup.java | 5 +- .../apache/fop/render/afp/fonts/AFPFontReader.java | 405 ++++++++++----------- .../apache/fop/render/afp/fonts/CharacterSet.java | 68 ++-- .../render/afp/fonts/CharacterSetOrientation.java | 10 +- .../fop/render/afp/fonts/FopCharacterSet.java | 2 +- .../apache/fop/render/afp/fonts/OutlineFont.java | 2 +- .../apache/fop/render/afp/fonts/RasterFont.java | 2 +- .../render/afp/tools/StructuredFieldReader.java | 7 +- 9 files changed, 252 insertions(+), 260 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index de6904d9b..ebd45457d 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -64,16 +64,16 @@ public class Font { /** logger */ private static Log log = LogFactory.getLog(Font.class); - private String fontName; - private FontTriplet triplet; - private int fontSize; + private final String fontName; + private final FontTriplet triplet; + private final int fontSize; /** * normal or small-caps font */ //private int fontVariant; - private FontMetrics metric; + private final FontMetrics metric; /** * Main constructor @@ -268,7 +268,8 @@ public class Font { width = getCharWidth(' '); } else { if (hasChar(c)) { - width = getWidth(mapChar(c)); + int mappedChar = mapChar(c); + width = getWidth(mappedChar); } else { width = -1; } diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index eea04a580..f7ad6fc65 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/src/java/org/apache/fop/fonts/FontSetup.java @@ -27,7 +27,6 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fonts.base14.Courier; import org.apache.fop.fonts.base14.CourierBold; import org.apache.fop.fonts.base14.CourierBoldOblique; @@ -202,7 +201,7 @@ public class FontSetup { if (resolver == null) { //Ensure that we have minimal font resolution capabilities - resolver = createMinimalFontResolver1(); + resolver = createMinimalFontResolver(); } String internalName = null; @@ -225,7 +224,7 @@ public class FontSetup { } /** @return a new FontResolver to be used by the font subsystem */ - public static FontResolver createMinimalFontResolver1() { + public static FontResolver createMinimalFontResolver() { return new FontResolver() { /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java index 7951be26c..0c190738c 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java +++ b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java @@ -26,12 +26,11 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.exceptions.FontRuntimeException; import org.apache.fop.render.afp.modca.AFPConstants; import org.apache.fop.render.afp.tools.StructuredFieldReader; @@ -111,143 +110,19 @@ public final class AFPFontReader { /** * The collection of code pages */ - private HashMap codePages = new HashMap(); + private final Map/*>*/ codePages + = new java.util.HashMap/*>*/(); /** - * Load the font details and metrics into the CharacterSetMetric object, - * this will use the actual afp code page and character set files to load - * the object with the necessary metrics. + * Returns an InputStream to a given file path and filename * - * @param characterSet the CharacterSetMetric object to populate - */ - public void loadCharacterSetMetric(CharacterSet characterSet) { - - InputStream inputStream = null; - - try { - - /** - * Get the code page which contains the character mapping - * information to map the unicode character id to the graphic - * chracter global identifier. - */ - String cp = new String(characterSet.getCodePage()); - String path = characterSet.getPath(); - - HashMap codepage = (HashMap) codePages.get(cp); - - if (codepage == null) { - codepage = loadCodePage(cp, characterSet.getEncoding(), path); - codePages.put(cp, codepage); - } - - /** - * Load the character set metric information, no need to cache this - * information as it should be cached by the objects that wish to - * load character set metric information. - */ - final String characterset = characterSet.getName(); - - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = AFPFontReader.class.getClassLoader(); - } - - URL url = classLoader.getResource(path); - if (url == null) { - try { - File file = new File(path); - url = file.toURI().toURL(); - if (url == null) { - String msg = "CharacterSet file not found for " - + characterset + " in classpath: " + path; - log.error(msg); - throw new FileNotFoundException(msg); - } - } catch (MalformedURLException ex) { - String msg = "CharacterSet file not found for " - + characterset + " in classpath: " + path; - log.error(msg); - throw new FileNotFoundException(msg); - } - - } - - File directory = new File(url.getPath()); - - final String filterpattern = characterset.trim(); - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.startsWith(filterpattern); - } - }; - - File[] csfont = directory.listFiles(filter); - if (csfont.length < 1) { - String msg = "CharacterSet file search for " + characterset - + " located " + csfont.length + " files"; - log.error(msg); - throw new FileNotFoundException(msg); - } else if (csfont.length > 1) { - String msg = "CharacterSet file search for " + characterset - + " located " + csfont.length + " files"; - log.warn(msg); - } - - inputStream = csfont[0].toURI().toURL().openStream(); - if (inputStream == null) { - String msg = "Failed to open character set resource " - + characterset; - log.error(msg); - throw new FileNotFoundException(msg); - } - - StructuredFieldReader sfr = new StructuredFieldReader(inputStream); - - // Process D3A789 Font Control - FontControl fnc = processFontControl(sfr); - - //process D3AE89 Font Orientation - CharacterSetOrientation[] csoArray = processFontOrientation(sfr); - - //process D3AC89 Font Position - processFontPosition(sfr, csoArray, fnc.getDpi()); - - //process D38C89 Font Index (per orientation) - for (int i = 0; i < csoArray.length; i++) { - processFontIndex(sfr, csoArray[i], codepage, fnc.getDpi()); - characterSet.addCharacterSetOrientation(csoArray[i]); - } - - } catch (Exception ex) { - throw new FontRuntimeException( - "Failed to load the character set metrics for code page " - + characterSet.getCodePage(), ex); - } finally { - try { - inputStream.close(); - } catch (Exception ex) { - // Ignore - } - } - - } - - /** - * Load the code page information from the appropriate file. The file name - * to load is determined by the code page name and the file extension 'CDP'. + * @param path the file path + * @param filename the file name + * @return an inputStream * - * @param codePage - * the code page identifier - * @param encoding - * the encoding to use for the character decoding + * @throws IOException in the event that an I/O exception of some sort has occurred */ - private static HashMap loadCodePage(String codePage, String encoding, - String path) throws IOException { - - // Create the HashMap to store code page information - HashMap codepages = new HashMap(); - + private InputStream openInputStream(String path, String filename) throws IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = AFPFontReader.class.getClassLoader(); @@ -260,14 +135,12 @@ public final class AFPFontReader { File file = new File(path); url = file.toURI().toURL(); if (url == null) { - String msg = "CodePage file not found for " + codePage - + " in classpath: " + path; + String msg = "file not found " + filename + " in classpath: " + path; log.error(msg); throw new FileNotFoundException(msg); } } catch (MalformedURLException ex) { - String msg = "CodePage file not found for " + codePage - + " in classpath: " + path; + String msg = "file not found " + filename + " in classpath: " + path; log.error(msg); throw new FileNotFoundException(msg); } @@ -280,115 +153,220 @@ public final class AFPFontReader { throw new FileNotFoundException(msg); } - final String filterpattern = codePage.trim(); + final String filterpattern = filename.trim(); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.startsWith(filterpattern); } }; - File[] codepage = directory.listFiles(filter); + File[] files = directory.listFiles(filter); - if (codepage.length < 1) { - String msg = "CodePage file search for " + codePage + " located " - + codepage.length + " files"; + if (files.length < 1) { + String msg = "file search for " + filename + " located " + + files.length + " files"; log.error(msg); throw new FileNotFoundException(msg); - } else if (codepage.length > 1) { - String msg = "CodePage file search for " + codePage + " located " - + codepage.length + " files"; + } else if (files.length > 1) { + String msg = "file search for " + filename + " located " + + files.length + " files"; log.warn(msg); } - InputStream is = codepage[0].toURI().toURL().openStream(); + InputStream inputStream = files[0].toURI().toURL().openStream(); - if (is == null) { - String msg = "AFPFontReader:: loadCodePage(String):: code page file not found for " - + codePage; + if (inputStream == null) { + String msg = "AFPFontReader:: getInputStream():: file not found for " + filename; log.error(msg); throw new FileNotFoundException(msg); } - StructuredFieldReader sfr = new StructuredFieldReader(is); - byte[] data = sfr.getNext(CHARACTER_TABLE_SF); + return inputStream; + } - int position = 0; - byte[] gcgiBytes = new byte[8]; - byte[] charBytes = new byte[1]; + /** + * 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()); + } + } - // Read data, ignoring bytes 0 - 2 - for (int index = 3; index < data.length; index++) { - if (position < 8) { - // Build the graphic character global identifier key - gcgiBytes[position] = data[index]; - position++; - } else if (position == 9) { - position = 0; - // Set the character - charBytes[0] = data[index]; - String gcgiString = new String(gcgiBytes, - AFPConstants.EBCIDIC_ENCODING); - String charString = new String(charBytes, encoding); -// int value = charString.charAt(0); - codepages.put(gcgiString, charString); + /** + * Load the font details and metrics into the CharacterSetMetric object, + * this will use the actual afp code page and character set files to load + * the object with the necessary metrics. + * + * @param characterSet the CharacterSetMetric object to populate + * @throws IOException if an I/O exception of some sort has occurred. + */ + public void loadCharacterSetMetric(CharacterSet characterSet) throws IOException { + + InputStream inputStream = null; + + try { + + /** + * Get the code page which contains the character mapping + * information to map the unicode character id to the graphic + * chracter global identifier. + */ + String codePageId = new String(characterSet.getCodePage()); + String path = characterSet.getPath(); + + Map/**/ codePage = (Map/**/)codePages.get(codePageId); + + if (codePage == null) { + codePage = loadCodePage(codePageId, characterSet.getEncoding(), path); + codePages.put(codePageId, codePage); + } + + /** + * Load the character set metric information, no need to cache this + * information as it should be cached by the objects that wish to + * load character set metric information. + */ + final String characterSetName = characterSet.getName(); + + inputStream = openInputStream(path, characterSetName); + + StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); + + // Process D3A789 Font Control + FontControl fontControl = processFontControl(structuredFieldReader); + + if (fontControl != null) { + //process D3AE89 Font Orientation + CharacterSetOrientation[] characterSetOrientations + = processFontOrientation(structuredFieldReader); + + int dpi = fontControl.getDpi(); + + //process D3AC89 Font Position + processFontPosition(structuredFieldReader, characterSetOrientations, dpi); + + //process D38C89 Font Index (per orientation) + for (int i = 0; i < characterSetOrientations.length; i++) { + processFontIndex(structuredFieldReader, + characterSetOrientations[i], codePage, dpi); + characterSet.addCharacterSetOrientation(characterSetOrientations[i]); + } } else { - position++; + throw new IOException( + "Failed to read font control structured field in character set " + + characterSetName); } + + } finally { + closeInputStream(inputStream); } + } + + /** + * Load the code page information from the appropriate file. The file name + * to load is determined by the code page name and the file extension 'CDP'. + * + * @param codePage + * the code page identifier + * @param encoding + * the encoding to use for the character decoding + * @returns a code page mapping + */ + private Map/**/ loadCodePage(String codePage, String encoding, + String path) throws IOException { + + // Create the HashMap to store code page information + Map/**/ codePages = new java.util.HashMap/**/(); + + InputStream inputStream = null; try { - is.close(); - } catch (Exception ex) { - // Ignore + inputStream = openInputStream(path, codePage.trim()); + + StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); + byte[] data = structuredFieldReader.getNext(CHARACTER_TABLE_SF); + + int position = 0; + byte[] gcgiBytes = new byte[8]; + byte[] charBytes = new byte[1]; + + // Read data, ignoring bytes 0 - 2 + for (int index = 3; index < data.length; index++) { + if (position < 8) { + // Build the graphic character global identifier key + gcgiBytes[position] = data[index]; + position++; + } else if (position == 9) { + position = 0; + // Set the character + charBytes[0] = data[index]; + String gcgiString = new String(gcgiBytes, + AFPConstants.EBCIDIC_ENCODING); + String charString = new String(charBytes, encoding); +// int value = charString.charAt(0); + codePages.put(gcgiString, charString); + } else { + position++; + } + } + } finally { + closeInputStream(inputStream); } - return codepages; - + return codePages; } /** * Process the font control details using the structured field reader. * - * @param sfr + * @param structuredFieldReader * the structured field reader */ - private static FontControl processFontControl(StructuredFieldReader sfr) + private FontControl processFontControl(StructuredFieldReader structuredFieldReader) throws IOException { - byte[] fncData = sfr.getNext(FONT_CONTROL_SF); + byte[] fncData = structuredFieldReader.getNext(FONT_CONTROL_SF); // int position = 0; + FontControl fontControl = null; + if (fncData != null) { + fontControl = new FontControl(); - FontControl fontControl = new AFPFontReader().new FontControl(); - - if (fncData[7] == (byte) 0x02) { - fontControl.setRelative(true); - } - - int dpi = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10; + if (fncData[7] == (byte) 0x02) { + fontControl.setRelative(true); + } - fontControl.setDpi(dpi); + int dpi = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10; + fontControl.setDpi(dpi); + } return fontControl; - } /** * Process the font orientation details from using the structured field * reader. * - * @param sfr + * @param structuredFieldReader * the structured field reader */ - private static CharacterSetOrientation[] processFontOrientation( - StructuredFieldReader sfr) throws IOException { + private CharacterSetOrientation[] processFontOrientation( + StructuredFieldReader structuredFieldReader) throws IOException { - byte[] data = sfr.getNext(FONT_ORIENTATION_SF); + byte[] data = structuredFieldReader.getNext(FONT_ORIENTATION_SF); int position = 0; byte[] fnoData = new byte[26]; - ArrayList orientations = new ArrayList(); + List orientations = new java.util.ArrayList(); // Read data, ignoring bytes 0 - 2 for (int index = 3; index < data.length; index++) { @@ -434,20 +412,20 @@ public final class AFPFontReader { * Populate the CharacterSetOrientation object in the suplied array with the * font position details using the supplied structured field reader. * - * @param sfr + * @param structuredFieldReader * the structured field reader - * @param csoArray + * @param characterSetOrientations * the array of CharacterSetOrientation objects */ - private static void processFontPosition(StructuredFieldReader sfr, - CharacterSetOrientation[] csoArray, int dpi) throws IOException { + private void processFontPosition(StructuredFieldReader structuredFieldReader, + CharacterSetOrientation[] characterSetOrientations, int dpi) throws IOException { - byte[] data = sfr.getNext(FONT_POSITION_SF); + byte[] data = structuredFieldReader.getNext(FONT_POSITION_SF); int position = 0; byte[] fpData = new byte[26]; - int csoIndex = 0; + int characterSetOrientationIndex = 0; int fopFactor = 0; switch (dpi) { @@ -475,7 +453,8 @@ public final class AFPFontReader { position = 0; - CharacterSetOrientation cso = csoArray[csoIndex]; + CharacterSetOrientation characterSetOrientation + = characterSetOrientations[characterSetOrientationIndex]; int xHeight = ((fpData[2] & 0xFF) << 8) + (fpData[3] & 0xFF); int capHeight = ((fpData[4] & 0xFF) << 8) + (fpData[5] & 0xFF); @@ -484,12 +463,12 @@ public final class AFPFontReader { dscHeight = dscHeight * -1; - cso.setXHeight(xHeight * fopFactor); - cso.setCapHeight(capHeight * fopFactor); - cso.setAscender(ascHeight * fopFactor); - cso.setDescender(dscHeight * fopFactor); + characterSetOrientation.setXHeight(xHeight * fopFactor); + characterSetOrientation.setCapHeight(capHeight * fopFactor); + characterSetOrientation.setAscender(ascHeight * fopFactor); + characterSetOrientation.setDescender(dscHeight * fopFactor); - csoIndex++; + characterSetOrientationIndex++; fpData[position] = data[index]; @@ -503,18 +482,18 @@ public final class AFPFontReader { /** * Process the font index details for the character set orientation. * - * @param sfr + * @param structuredFieldReader * the structured field reader * @param cso * the CharacterSetOrientation object to populate * @param codepage * the map of code pages */ - private static void processFontIndex(StructuredFieldReader sfr, - CharacterSetOrientation cso, HashMap codepage, int dpi) + private void processFontIndex(StructuredFieldReader structuredFieldReader, + CharacterSetOrientation cso, Map/**/ codepage, int dpi) throws IOException { - byte[] data = sfr.getNext(FONT_INDEX_SF); + byte[] data = structuredFieldReader.getNext(FONT_INDEX_SF); int fopFactor = 0; @@ -545,14 +524,14 @@ public final class AFPFontReader { // Read data, ignoring bytes 0 - 2 for (int index = 3; index < data.length; index++) { if (position < 8) { - gcgid[position] = (byte) data[index]; + gcgid[position] = data[index]; position++; } else if (position < 27) { - fiData[position - 8] = (byte) data[index]; + fiData[position - 8] = data[index]; position++; } else if (position == 27) { - fiData[position - 8] = (byte) data[index]; + fiData[position - 8] = data[index]; position = 0; diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java index 434f541a4..f7680b15c 100644 --- a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java @@ -19,6 +19,7 @@ package org.apache.fop.render.afp.fonts; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Map; @@ -49,6 +50,15 @@ public class CharacterSet { /** Static logging instance */ protected static final Log log = LogFactory.getLog(CharacterSet.class.getName()); + /** default codepage */ + protected static final String DEFAULT_CODEPAGE = "T1V10500"; + + /** default encoding */ + protected static final String DEFAULT_ENCODING = "Cp500"; + + private static final int MAX_NAME_LEN = 8; + + /** The code page to which the character set relates */ protected String codePage; @@ -64,8 +74,8 @@ public class CharacterSet { /** Indicator as to whether to metrics have been loaded */ private boolean isMetricsLoaded = false; - /** The current orientation (currently only 0 is suppoted by FOP) */ - private String currentOrientation = "0"; + /** The current orientation (currently only 0 is supported by FOP) */ + private final String currentOrientation = "0"; /** The collection of objects for each orientation */ private Map characterSetOrientations = null; @@ -79,27 +89,23 @@ public class CharacterSet { * @param name the character set name * @param path the path to the installed afp fonts */ - public CharacterSet( - String codePage, - String encoding, - String name, - String path) { - - if (name.length() > 8) { - String msg = "Character set name must be a maximum of 8 characters " + name; + public CharacterSet(String codePage, String encoding, String name, String path) { + if (name.length() > MAX_NAME_LEN) { + String msg = "Character set name '" + name + "' must be a maximum of " + + MAX_NAME_LEN + " characters"; log.error("Constructor:: " + msg); throw new IllegalArgumentException(msg); } - if (name.length() < 8) { - this.name = StringUtils.rpad(name, ' ', 8); + if (name.length() < MAX_NAME_LEN) { + this.name = StringUtils.rpad(name, ' ', MAX_NAME_LEN); } else { this.name = name; } - this.codePage = codePage; this.encoding = encoding; this.path = path; + this.characterSetOrientations = new java.util.HashMap(4); } @@ -121,7 +127,7 @@ public class CharacterSet { * a character rotation other than 0, ascender height loses its * meaning when the character is lying on its side or is upside down * with respect to normal viewing orientation. For the general case, - * Ascender Height is the character�s most positive y-axis value. + * Ascender Height is the characters most positive y-axis value. * For bounded character boxes, for a given character having an * ascender, ascender height and baseline offset are equal. * @@ -157,9 +163,9 @@ public class CharacterSet { } /** - * The first character in the character set + * Returns the first character in the character set * - * @return the first character + * @return the first character in the character set */ public int getFirstChar() { load(); @@ -169,7 +175,7 @@ public class CharacterSet { /** * Returns the last character in the character set * - * @return the last character + * @return the last character in the character set */ public int getLastChar() { load(); @@ -197,6 +203,7 @@ public class CharacterSet { /** * XHeight refers to the height of the lower case letters above the baseline. + * * @return the typical height of characters */ public int getXHeight() { @@ -211,9 +218,9 @@ public class CharacterSet { * @param character the character from which the width will be calculated * @return the width of the character */ - public int width(int character) { + public int getWidth(int character) { load(); - return getCharacterSetOrientation().width(character); + return getCharacterSetOrientation().getWidth(character); } /** @@ -223,24 +230,30 @@ public class CharacterSet { private void load() { if (!isMetricsLoaded) { AFPFontReader afpFontReader = new AFPFontReader(); - afpFontReader.loadCharacterSetMetric(this); - isMetricsLoaded = true; + try { + afpFontReader.loadCharacterSetMetric(this); + isMetricsLoaded = true; + } catch (IOException e) { + String msg = "Failed to load the character set metrics for code page " + codePage; + log.error(msg); + throw new RuntimeException(e.getMessage()); + } } } /** * Returns the AFP character set identifier * - * @return String + * @return the AFP character set identifier */ public String getName() { return name; } /** - * Returns the AFP character set identifier + * Returns the AFP character set identifier as a byte array * - * @return the AFP character set identifier + * @return the AFP character set identifier as a byte array */ public byte[] getNameBytes() { byte[] nameBytes = null; @@ -249,8 +262,7 @@ public class CharacterSet { } catch (UnsupportedEncodingException usee) { nameBytes = name.getBytes(); log.warn( - "UnsupportedEncodingException translating the name " - + name); + "UnsupportedEncodingException translating the name " + name); } return nameBytes; } @@ -281,16 +293,14 @@ public class CharacterSet { * implementation (whenever FOP implement the mechanism). This is also * the case for landscape prints which use an orientation of 270 degrees, * in 99.9% of cases the font metrics will be the same as the 0 degrees - * therefore the implementation currely will always use 0 degrees. + * therefore the implementation currently will always use 0 degrees. * * @return characterSetOrentation The current orientation metrics. */ private CharacterSetOrientation getCharacterSetOrientation() { - CharacterSetOrientation c = (CharacterSetOrientation) characterSetOrientations.get(currentOrientation); return c; - } /** diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java index be6dbf6ea..e13029717 100644 --- a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java +++ b/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java @@ -183,11 +183,15 @@ public class CharacterSetOrientation { /** * Get the width (in 1/1000ths of a point size) of the character * identified by the parameter passed. - * @param character the character to evaluate + * @param characterIndex the character to evaluate * @return the widths of the character */ - public int width(int character) { - return chars[character]; + public int getWidth(int characterIndex) { + if (characterIndex >= chars.length) { + throw new IllegalArgumentException("Invalid character index: " + + characterIndex + ", maximum is " + (chars.length - 1)); + } + return chars[characterIndex]; } /** diff --git a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java index f6864d73f..d5beb5a33 100644 --- a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java +++ b/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java @@ -125,7 +125,7 @@ public class FopCharacterSet extends CharacterSet { * @param character the character from which the width will be calculated * @return the width of the character */ - public int width(int character) { + public int getWidth(int character) { return charSet.getWidth(character, size); } diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java index f8dd9a1ed..71c5dfb6f 100644 --- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java @@ -136,7 +136,7 @@ public class OutlineFont extends AFPFont { * @return the width of the character for the specified point size */ public int getWidth(int character, int size) { - return charSet.width(character) / 1000 * size; + return charSet.getWidth(character) / 1000 * size; } /** diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java index 8312dca72..5c1696aa4 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -196,7 +196,7 @@ public class RasterFont extends AFPFont { * @return the width for the given point size */ public int getWidth(int character, int size) { - return getCharacterSet(size).width(character); + return getCharacterSet(size).getWidth(character); } /** diff --git a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java b/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java index 1939d2dda..48beff023 100644 --- a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java +++ b/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java @@ -58,14 +58,14 @@ public class StructuredFieldReader { * parameter (this must be a valid MO:DCA structured field. * @param identifier the three byte identifier * @throws IOException if an I/O exception occurred - * @return the next structured field + * @return the next structured field or null when there are no more */ public byte[] getNext(byte[] identifier) throws IOException { int bufferPointer = 0; byte[] bufferData = new byte[identifier.length + 2]; for (int x = 0; x < identifier.length; x++) { - bufferData[x] = (byte) 0; + bufferData[x] = 0x00; } int c; @@ -128,7 +128,6 @@ public class StructuredFieldReader { } - return new byte[] { - }; + return null; } } -- cgit v1.2.3 From 46c9aca22be22f20ed5bddbf21618ed1abdfe287 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 24 Oct 2008 13:42:59 +0000 Subject: Fixed a problem where the BPD or a block area could be wrong if there is a nested, absolutely positioned area (for example a block-container). This was most probably introduced by rev 618992. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@707631 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/area/Block.java | 2 +- .../fop/layoutmgr/list/ListItemLayoutManager.java | 17 +++---- status.xml | 4 ++ .../block-container_area-bpd.xml | 59 ++++++++++++++++++++++ 4 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block-container_area-bpd.xml (limited to 'src/java') diff --git a/src/java/org/apache/fop/area/Block.java b/src/java/org/apache/fop/area/Block.java index 7a2465859..5faec9f7a 100644 --- a/src/java/org/apache/fop/area/Block.java +++ b/src/java/org/apache/fop/area/Block.java @@ -79,7 +79,7 @@ public class Block extends BlockParent { * @param autoHeight increase the height of the block. */ public void addBlock(Block block, boolean autoHeight) { - if (autoHeight && allowBPDUpdate) { + if (autoHeight && allowBPDUpdate && block.isStacked()) { bpd += block.getAllocBPD(); } addChildArea(block); diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index d83cca642..a4e8982f7 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -26,6 +26,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; @@ -537,14 +538,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager label.addAreas(labelIter, lc); } - // reset the area bpd after adding the label areas and before adding the body areas - int savedBPD = 0; - if (labelFirstIndex <= labelLastIndex - && bodyFirstIndex <= bodyLastIndex) { - savedBPD = curBlockArea.getBPD(); - curBlockArea.setBPD(0); - } - // add body areas if (bodyFirstIndex <= bodyLastIndex) { KnuthPossPosIter bodyIter = new KnuthPossPosIter(bodyList, @@ -559,9 +552,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } // after adding body areas, set the maximum area bpd - if (curBlockArea.getBPD() < savedBPD) { - curBlockArea.setBPD(savedBPD); + int childCount = curBlockArea.getChildAreas().size(); + assert childCount >= 1 && childCount <= 2; + int itemBPD = ((Block)curBlockArea.getChildAreas().get(0)).getAllocBPD(); + if (childCount == 2) { + itemBPD = Math.max(itemBPD, ((Block)curBlockArea.getChildAreas().get(1)).getAllocBPD()); } + curBlockArea.setBPD(itemBPD); addMarkersToPage(false, isFirst(firstPos), isLast(lastPos)); diff --git a/status.xml b/status.xml index ae924fce2..046416b59 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,10 @@ + + Fixed a problem where the BPD or a block area could be wrong if there is a nested, + absolutely positioned area (for example a block-container). + Bugzilla 40798: A conditional-page-master-reference with page-position="last" qualifies for a first page, if it is also the last. Additionally: also added support for diff --git a/test/layoutengine/standard-testcases/block-container_area-bpd.xml b/test/layoutengine/standard-testcases/block-container_area-bpd.xml new file mode 100644 index 000000000..9c00c8185 --- /dev/null +++ b/test/layoutengine/standard-testcases/block-container_area-bpd.xml @@ -0,0 +1,59 @@ + + + + + +

+ This test checks bpd values on block-containers. +

+
+ + + + + + + + + + Testing area BPDs... + + + bc1 + + + + Below + + + Above + + + + + + + + + + + + + + +
-- cgit v1.2.3 From 5f10442af0ea4cc6d672a6d77f49f831e358058e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 26 Oct 2008 16:32:16 +0000 Subject: Bugzilla 45113: Added PDF /Launch action, which is used in case of references to URIs using the file:// protocol. Thanks to Alexander Stamenov (astamenov.AT.gmail.com) for the input! git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@708012 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFDocument.java | 35 +++++++++----- src/java/org/apache/fop/pdf/PDFFactory.java | 35 ++++++++++++++ src/java/org/apache/fop/pdf/PDFLaunch.java | 68 ++++++++++++++++++++++++++++ status.xml | 5 ++ 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 src/java/org/apache/fop/pdf/PDFLaunch.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index 16ec81049..598fd433e 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -223,6 +223,11 @@ public class PDFDocument { */ protected List gotos = new java.util.ArrayList(); + /** + * List of PDFLaunch objects. + */ + protected List launches = new java.util.ArrayList(); + /** * The PDFDests object for the name dictionary. * Note: This object is not a list. @@ -486,6 +491,9 @@ public class PDFDocument { if (obj instanceof PDFPage) { this.pages.notifyKidRegistered((PDFPage)obj); } + if (obj instanceof PDFLaunch) { + this.launches.add(obj); + } if (obj instanceof PDFLink) { this.links.add(obj); } @@ -656,6 +664,15 @@ public class PDFDocument { return (PDFGoTo)findPDFObject(gotos, compare); } + /** + * Finds a launch. + * @param compare reference object to use as search template + * @return the launch if found, null otherwise + */ + protected PDFLaunch findLaunch(PDFLaunch compare) { + return (PDFLaunch) findPDFObject(launches, compare); + } + /** * Looks for an existing GState to use * @param wanted requested features @@ -703,7 +720,6 @@ public class PDFDocument { */ public void setColorSpace(int theColorspace) { this.colorspace.setColorSpace(theColorspace); - return; } /** @@ -1019,12 +1035,6 @@ public class PDFDocument { by the table's length */ this.position += outputXref(stream); - // Determine existance of encryption dictionary - String encryptEntry = ""; - if (this.encryption != null) { - encryptEntry = this.encryption.getTrailerEntry(); - } - /* construct the trailer */ String pdf = "trailer\n" @@ -1037,10 +1047,13 @@ public class PDFDocument { + "\n" + "/Info " + this.info.referencePDF() - + "\n" - + getIDEntry() - + "\n" - + encryptEntry + + "\n"; + if (this.encryption != null) { + pdf += this.encryption.getTrailerEntry(); + } else { + pdf += getIDEntry(); + } + pdf += "\n" + ">>\n" + "startxref\n" + this.xref diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index fc6e6b9fa..a5beb4ec7 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1011,6 +1011,10 @@ public class PDFFactory { // HTTP URL? if (targetLo.startsWith("http://")) { return new PDFUri(target); + // Non PDF files. Try to /Launch them. + } else if (targetLo.startsWith("file://")) { + target = target.substring("file://".length()); + return getLaunchAction(target); // Bare PDF file name? } else if (targetLo.endsWith(".pdf")) { return getGoToPDFAction(target, null, -1, newWindow); @@ -1104,6 +1108,37 @@ public class PDFFactory { return remote; } + /** + * Creates and returns a launch pdf document action using + * file to create a file spcifiaciton for + * the document/file to be opened with an external application. + * + * @param file the pdf file name + * @return the pdf launch object + */ + private PDFLaunch getLaunchAction(String file) { + getDocument().getProfile().verifyActionAllowed(); + + PDFFileSpec fileSpec = new PDFFileSpec(file); + PDFFileSpec oldSpec = getDocument().findFileSpec(fileSpec); + + if (oldSpec == null) { + getDocument().registerObject(fileSpec); + } else { + fileSpec = oldSpec; + } + PDFLaunch launch = new PDFLaunch(fileSpec); + PDFLaunch oldLaunch = getDocument().findLaunch(launch); + + if (oldLaunch == null) { + getDocument().registerObject(launch); + } else { + launch = oldLaunch; + } + + return launch; + } + /** * Make an outline object and add it to the given parent * diff --git a/src/java/org/apache/fop/pdf/PDFLaunch.java b/src/java/org/apache/fop/pdf/PDFLaunch.java new file mode 100644 index 000000000..d87fa2523 --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFLaunch.java @@ -0,0 +1,68 @@ +/* + * 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.pdf; + +/** + * This class represents the /Launch action. + */ +public class PDFLaunch extends PDFAction { + + private PDFFileSpec externalFileSpec; + + public PDFLaunch(PDFFileSpec fileSpec) { + this.externalFileSpec = fileSpec; + } + + public String getAction() { + return this.referencePDF(); + } + + public String toPDFString() { + StringBuffer sb = new StringBuffer(64); + sb.append(getObjectID()); + sb.append("<<\n/S /Launch\n/F "); + sb.append(externalFileSpec.referencePDF()); + sb.append(" \n>>\nendobj\n"); + + return sb.toString(); + } + + /** + * Check if this equals another object. + * + * @param obj the object to compare + * @return true if this equals other object + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || !(obj instanceof PDFLaunch)) { + return false; + } + + PDFLaunch launch = (PDFLaunch) obj; + + if (!launch.externalFileSpec.referencePDF().equals(externalFileSpec.referencePDF())) { + return false; + } + + return true; + } +} diff --git a/status.xml b/status.xml index 046416b59..85cd31935 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,11 @@ + + Added PDF /Launch action: references to URIs using the file:// protocol will now generate + a /Launch action as opposed to a more general /URI (which doesn't yield the expected result + for this protocol). + Fixed a problem where the BPD or a block area could be wrong if there is a nested, absolutely positioned area (for example a block-container). -- cgit v1.2.3 From 8b98afa774a23b94e142c350f32b3f88159d262f Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 17 Nov 2008 18:18:20 +0000 Subject: Bugzilla 46211: Fixed some multi-threading issues in FontCache.java (+ some minor cleanup: simplification of conditionals) Thanks to rogov.AT.devexperts.com for tracing and reporting the problem. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@718309 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontCache.java | 42 ++++++++++------------------ status.xml | 9 ++++++ 2 files changed, 23 insertions(+), 28 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 2528989bb..a3ff1b672 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -48,7 +48,7 @@ public final class FontCache implements Serializable { * Serialization Version UID. Change this value if you want to make sure the user's cache * file is purged after an update. */ - private static final long serialVersionUID = 605232520271754718L; + private static final long serialVersionUID = 605232520271754719L; /** logging instance */ private static Log log = LogFactory.getLog(FontCache.class); @@ -64,7 +64,7 @@ public final class FontCache implements Serializable { private transient boolean changed = false; /** change lock */ - private transient Object changeLock = new Object(); + private final Object changeLock = new Object(); /** master mapping of font url -> font info. This needs to be * a list, since a TTC file may contain more than 1 font. */ @@ -80,12 +80,6 @@ public final class FontCache implements Serializable { //nop } - private void readObject(java.io.ObjectInputStream in) - throws IOException, ClassNotFoundException { - in.defaultReadObject(); - this.changeLock = new Object(); //Initialize transient field - } - private static File getUserHome() { String s = System.getProperty("user.home"); if (s != null) { @@ -226,10 +220,8 @@ public final class FontCache implements Serializable { * @return boolean */ public boolean containsFont(String embedUrl) { - if (embedUrl != null) { - return getFontFileMap().containsKey(embedUrl); - } - return false; + return (embedUrl != null + && getFontFileMap().containsKey(embedUrl)); } /** @@ -238,10 +230,8 @@ public final class FontCache implements Serializable { * @return font */ public boolean containsFont(EmbedFontInfo fontInfo) { - if (fontInfo != null) { - return getFontFileMap().containsKey(getCacheKey(fontInfo)); - } - return false; + return (fontInfo != null + && getFontFileMap().containsKey(getCacheKey(fontInfo))); } /** @@ -316,10 +306,7 @@ public final class FontCache implements Serializable { * @return CachedFontFile object */ public CachedFontFile getFontFile(String embedUrl) { - if (containsFont(embedUrl)) { - return (CachedFontFile)getFontFileMap().get(embedUrl); - } - return null; + return containsFont(embedUrl) ? (CachedFontFile) getFontFileMap().get(embedUrl) : null; } /** @@ -362,8 +349,8 @@ public final class FontCache implements Serializable { * @return whether this is a failed font */ public boolean isFailedFont(String embedUrl, long lastModified) { - if (getFailedFontMap().containsKey(embedUrl)) { - synchronized (changeLock) { + synchronized (changeLock) { + if (getFailedFontMap().containsKey(embedUrl)) { long failedLastModified = ((Long)getFailedFontMap().get(embedUrl)).longValue(); if (lastModified != failedLastModified) { // this font has been changed so lets remove it @@ -371,10 +358,11 @@ public final class FontCache implements Serializable { getFailedFontMap().remove(embedUrl); changed = true; } + return true; + } else { + return false; } - return true; } - return false; } /** @@ -457,10 +445,8 @@ public final class FontCache implements Serializable { } public boolean containsFont(EmbedFontInfo efi) { - if (efi.getPostScriptName() != null) { - return getFileFontsMap().containsKey(efi.getPostScriptName()); - } - return false; + return efi.getPostScriptName() != null + && getFileFontsMap().containsKey(efi.getPostScriptName()); } public EmbedFontInfo[] getEmbedFontInfos() { diff --git a/status.xml b/status.xml index 85cd31935..2197bc005 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,15 @@ + + Fixed some multi-threading issues in FontCache.java: +
    +
  • remove the unused private readObject()
  • +
  • make the changeLock member final (initialization-safety + impossible to reassign)
  • +
  • perform the HashMap check for a failed font inside the synchronized block to avoid a race condition
  • +
+
+
Added PDF /Launch action: references to URIs using the file:// protocol will now generate a /Launch action as opposed to a more general /URI (which doesn't yield the expected result -- cgit v1.2.3 From 3c666992c4e6159b6bbc0f5f5fa103dc835f2c08 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Tue, 18 Nov 2008 13:56:52 +0000 Subject: TextHandler interface changes, the Graphics2D implementation is now passed to drawString(). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@718591 13f79535-47bb-0310-9956-ffa450edef68 --- lib/xmlgraphics-commons-1.4svn.jar | Bin 528722 -> 530350 bytes .../apache/fop/render/ps/AbstractPSTranscoder.java | 16 ++++++++-------- .../apache/fop/render/ps/NativeTextHandler.java | 18 +++++++++++++----- .../org/apache/fop/render/ps/PSSVGHandler.java | 17 ++++++++--------- 4 files changed, 29 insertions(+), 22 deletions(-) (limited to 'src/java') diff --git a/lib/xmlgraphics-commons-1.4svn.jar b/lib/xmlgraphics-commons-1.4svn.jar index 7328fa62b..16ac2ef32 100644 Binary files a/lib/xmlgraphics-commons-1.4svn.jar and b/lib/xmlgraphics-commons-1.4svn.jar differ diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index b8ff8ef3f..374b5a256 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -25,21 +25,20 @@ import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; -import org.w3c.dom.Document; -import org.w3c.dom.svg.SVGLength; - import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.ImageTranscoder; -import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; -import org.apache.xmlgraphics.java2d.TextHandler; - import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.svg.AbstractFOPTranscoder; +import org.apache.xmlgraphics.java2d.TextHandler; +import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; +import org.w3c.dom.Document; +import org.w3c.dom.svg.SVGLength; /** * This class enables to transcode an input to a PostScript document. @@ -70,7 +69,7 @@ import org.apache.fop.svg.AbstractFOPTranscoder; */ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { - private Configuration cfg = null; + private final Configuration cfg = null; protected AbstractPSDocumentGraphics2D graphics = null; /** @@ -99,7 +98,8 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { FontInfo fontInfo = new FontInfo(); //TODO Do custom font configuration here somewhere/somehow FontSetup.setup(fontInfo); - graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); + PSGenerator generator = graphics.getPSGenerator(); + graphics.setCustomTextHandler(new NativeTextHandler(generator, fontInfo)); } super.transcode(document, uri, output); diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 9f62097e9..98addd19e 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -19,6 +19,7 @@ package org.apache.fop.render.ps; +import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.io.IOException; @@ -37,7 +38,7 @@ import org.apache.xmlgraphics.ps.PSGenerator; */ public class NativeTextHandler implements PSTextHandler { - private PSGraphics2D g2d; + private final PSGenerator gen; /** FontInfo containing all available fonts */ protected FontInfo fontInfo; @@ -59,8 +60,8 @@ public class NativeTextHandler implements PSTextHandler { * @param g2d the PSGraphics2D instance this instances is used by * @param fontInfo the FontInfo object with all available fonts */ - public NativeTextHandler(PSGraphics2D g2d, FontInfo fontInfo) { - this.g2d = g2d; + public NativeTextHandler(PSGenerator gen, FontInfo fontInfo) { + this.gen = gen; if (fontInfo != null) { this.fontInfo = fontInfo; } else { @@ -83,7 +84,7 @@ public class NativeTextHandler implements PSTextHandler { } private PSGenerator getPSGenerator() { - return this.g2d.getPSGenerator(); + return this.gen; } /** {@inheritDoc} */ @@ -98,12 +99,19 @@ public class NativeTextHandler implements PSTextHandler { //nop } + /** {@inheritDoc} */ + public void drawString(String text, float x, float y) throws IOException { + // TODO Remove me after removing the deprecated method in TextHandler. + throw new UnsupportedOperationException("Deprecated method!"); + } + /** * Draw a string to the PostScript document. The text is painted using * text operations. * {@inheritDoc} */ - public void drawString(String s, float x, float y) throws IOException { + public void drawString(Graphics2D g, String s, float x, float y) throws IOException { + PSGraphics2D g2d = (PSGraphics2D)g; g2d.preparePainting(); if (this.overrideFont == null) { java.awt.Font awtFont = g2d.getFont(); diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index d4a478fa4..2bc0f069b 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -24,18 +24,12 @@ import java.awt.geom.AffineTransform; import java.io.IOException; import java.util.Map; -import org.w3c.dom.Document; - import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.ps.PSGenerator; - import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; @@ -43,6 +37,9 @@ import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; +import org.w3c.dom.Document; /** * PostScript XML handler for SVG. Uses Apache Batik for SVG processing. @@ -262,7 +259,9 @@ public class PSSVGHandler extends AbstractGenericSVGHandler NativeTextHandler nativeTextHandler = null; BridgeContext ctx = new BridgeContext(ua); if (!strokeText) { - nativeTextHandler = new NativeTextHandler(graphics, psInfo.getFontInfo()); + PSGenerator generator = graphics.getPSGenerator(); + FontInfo fontInfo = psInfo.getFontInfo(); + nativeTextHandler = new NativeTextHandler(generator, fontInfo); graphics.setCustomTextHandler(nativeTextHandler); PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); ctx.setTextPainter(textPainter); @@ -283,8 +282,8 @@ public class PSSVGHandler extends AbstractGenericSVGHandler float w = (float)ctx.getDocumentSize().getWidth() * 1000f; float h = (float)ctx.getDocumentSize().getHeight() * 1000f; - float sx = psInfo.getWidth() / (float)w; - float sy = psInfo.getHeight() / (float)h; + float sx = psInfo.getWidth() / w; + float sy = psInfo.getHeight() / h; ctx = null; builder = null; -- cgit v1.2.3 From b9b72cfc2aae63c0c6c59edf87250010e6e79c9c Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 18 Nov 2008 17:58:54 +0000 Subject: Bugfix: do not reset TextLM.hasChanged, but combine (||) with previous value. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@718666 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 459bce0e8..27ed38b53 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -910,7 +910,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } startIndex = stopIndex; } - this.hasChanged = !nothingChanged; + this.hasChanged = (this.hasChanged || !nothingChanged); } /** {@inheritDoc} */ -- cgit v1.2.3 From 1ba2dd57a6702b9b0f4371d57c8b9642b4b048c7 Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Tue, 18 Nov 2008 20:14:22 +0000 Subject: Change FontCache.changeLock to a boolean[1], so it can be serialized... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@718705 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fonts/FontCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index a3ff1b672..fceeacb7b 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -64,7 +64,7 @@ public final class FontCache implements Serializable { private transient boolean changed = false; /** change lock */ - private final Object changeLock = new Object(); + private final boolean[] changeLock = new boolean[1]; /** master mapping of font url -> font info. This needs to be * a list, since a TTC file may contain more than 1 font. */ -- cgit v1.2.3 From 45c1746b5f718f40e9a9dd013a6e9249eb144fe8 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Wed, 19 Nov 2008 19:46:45 +0000 Subject: Reduced warning on ascender+descender > EM box to DEBUG level, as this case is compensated for by additional code in guessVerticalMetricsFromGlyphBBox() and is therefore only confusing. I tested problematic fonts and they show an acceptable line layout. No semantics changed. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@719038 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fonts/truetype/TTFFile.java | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 409b3908b..7198888f1 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -1248,10 +1248,11 @@ public class TTFFile { } } - log.debug("Font box height: " + (ascender - descender)); - if (ascender - descender > upem) { - log.warn("Ascender and descender together are larger than the em box." - + " This could lead to a wrong baseline placement in Apache FOP."); + if (log.isDebugEnabled()) { + log.debug("Font box height: " + (ascender - descender)); + if (ascender - descender > upem) { + log.debug("Ascender and descender together are larger than the em box."); + } } } @@ -1259,7 +1260,7 @@ public class TTFFile { // Approximate capHeight from height of "H" // It's most unlikely that a font misses the PCLT table // This also assumes that postscriptnames exists ("H") - // Should look it up int the cmap (that wouldn't help + // Should look it up in the cmap (that wouldn't help // for charsets without H anyway...) // Same for xHeight with the letter "x" int localCapHeight = 0; @@ -1294,10 +1295,12 @@ public class TTFFile { } } } - log.debug("Ascender from glyph 'd': " + localAscender - + " " + convertTTFUnit2PDFUnit(localAscender)); - log.debug("Descender from glyph 'p': " + localDescender - + " " + convertTTFUnit2PDFUnit(localDescender)); + if (log.isDebugEnabled()) { + log.debug("Ascender from glyph 'd': " + localAscender + + " " + convertTTFUnit2PDFUnit(localAscender)); + log.debug("Descender from glyph 'p': " + localDescender + + " " + convertTTFUnit2PDFUnit(localDescender)); + } if (ascender - descender > upem) { log.debug("Replacing specified ascender/descender with derived values to get values" + " which fit in the em box."); @@ -1305,10 +1308,12 @@ public class TTFFile { descender = localDescender; } - log.debug("xHeight from glyph 'x': " + localXHeight - + " " + convertTTFUnit2PDFUnit(localXHeight)); - log.debug("CapHeight from glyph 'H': " + localCapHeight - + " " + convertTTFUnit2PDFUnit(localCapHeight)); + if (log.isDebugEnabled()) { + log.debug("xHeight from glyph 'x': " + localXHeight + + " " + convertTTFUnit2PDFUnit(localXHeight)); + log.debug("CapHeight from glyph 'H': " + localCapHeight + + " " + convertTTFUnit2PDFUnit(localCapHeight)); + } if (capHeight == 0) { capHeight = localCapHeight; if (capHeight == 0) { -- cgit v1.2.3 From f15eca494468c55454bbc20dee20bb874f39c5ab Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 19 Nov 2008 22:45:06 +0000 Subject: Bugzilla 46240: Fixed a bug in combining break-before with a span change. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@719110 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/layoutmgr/FlowLayoutManager.java | 9 ++-- .../org/apache/fop/layoutmgr/LayoutContext.java | 26 ++++++++-- status.xml | 3 ++ .../block_break-before_bug46240.xml | 59 ++++++++++++++++++++++ 4 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 test/layoutengine/standard-testcases/block_break-before_bug46240.xml (limited to 'src/java') diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 293d6dbe0..42f08a42d 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -50,8 +50,6 @@ public class FlowLayoutManager extends BlockStackingLayoutManager /** Array of areas currently being filled stored by area class */ private BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX]; - private int currentSpan = EN_NONE; - /** * This is the top level layout manager. * It is created by the PageSequence FO. @@ -89,10 +87,11 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } else if (curLM instanceof BlockContainerLayoutManager) { span = ((BlockContainerLayoutManager)curLM).getBlockContainerFO().getSpan(); } + + int currentSpan = context.getCurrentSpan(); if (currentSpan != span) { log.debug("span change from " + currentSpan + " to " + span); context.signalSpanChange(span); - currentSpan = span; SpaceResolver.resolveElementList(returnList); return returnList; } @@ -228,7 +227,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager oldElement = (KnuthElement)oldListIterator.next(); if (oldElement.getPosition() instanceof NonLeafPosition) { // oldElement was created by a descendant of this FlowLM - oldElement.setPosition(((NonLeafPosition)oldElement.getPosition()).getPosition()); + oldElement.setPosition((oldElement.getPosition()).getPosition()); } else { // thisElement was created by this FlowLM, remove it oldListIterator.remove(); @@ -344,7 +343,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager * @return the BPD of the content area */ public int getContentAreaBPD() { - return (int) getCurrentPV().getBodyRegion().getBPD(); + return getCurrentPV().getBodyRegion().getBPD(); } } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 8b716dfde..3526ed239 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -88,7 +88,8 @@ public class LayoutContext { */ private MinOptMax stackLimitIP; - /** True if current element list is spanning in multi-column layout. */ + /** to keep track of spanning in multi-column layout */ + private int currentSpan = Constants.NOT_SET; private int nextSpan = Constants.NOT_SET; /** inline-progression-dimension of nearest ancestor reference area */ @@ -522,22 +523,37 @@ public class LayoutContext { } /** - * @return true if the current element list ends early because of a span change - * in multi-column layout. + * @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE} + * {@link Constants#EN_ALL} */ public int getNextSpan() { return nextSpan; } + /** + * @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE} + * {@link Constants#EN_ALL} + */ + public int getCurrentSpan() { + return (currentSpan == Constants.NOT_SET) + ? Constants.EN_NONE : currentSpan; + } + /** * Used to signal the PSLM that the element list ends early because of a span change in * multi-column layout. * @param span the new span value (legal values: NOT_SET, EN_NONE, EN_ALL) */ public void signalSpanChange(int span) { - if (span == Constants.NOT_SET || span == Constants.EN_NONE || span == Constants.EN_ALL) { + switch (span) { + case Constants.NOT_SET: + case Constants.EN_NONE: + case Constants.EN_ALL: + this.currentSpan = this.nextSpan; this.nextSpan = span; - } else { + break; + default: + assert false; throw new IllegalArgumentException("Illegal value on signalSpanChange() for span: " + span); } diff --git a/status.xml b/status.xml index aa86a08c0..2a951cb42 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,9 @@ + + Fixed a bug when combining break-before with a span change. + Fixed some multi-threading issues in FontCache.java:
    diff --git a/test/layoutengine/standard-testcases/block_break-before_bug46240.xml b/test/layoutengine/standard-testcases/block_break-before_bug46240.xml new file mode 100644 index 000000000..c59dbb42e --- /dev/null +++ b/test/layoutengine/standard-testcases/block_break-before_bug46240.xml @@ -0,0 +1,59 @@ + + + + + +

    + Test for Bugzilla #46240: break-before breaks span-change. +

    +
    + + + + + + + + + + + + + + xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx + + + + + + + + xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx + + + + + + + + + + + + +
    -- cgit v1.2.3 From d62f5f811c40bc3f0b20f0ae8d75cfb240be9c67 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 21 Nov 2008 16:07:58 +0000 Subject: Added support for SVG 1.2 inside fo:instream-foreign-object. The code just used the basic SVGDOMImplementation for SVG 1.1. Now it delegates the DOM building to Batik code instead of to a normal DOM builder. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@719616 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/XMLObj.java | 1 + .../svg/SVGDOMContentHandlerFactory.java | 82 ++++++++++++++++++++++ .../apache/fop/fo/extensions/svg/SVGElement.java | 61 +++++----------- .../apache/fop/svg/FOPSAXSVGDocumentFactory.java | 11 +++ status.xml | 3 + 5 files changed, 113 insertions(+), 45 deletions(-) create mode 100644 src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java (limited to 'src/java') diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index 3330f41a5..e1eb47b46 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -217,6 +217,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** {@inheritDoc} */ public void notifyObjectBuilt(Object obj) { this.doc = (Document)obj; + this.element = this.doc.getDocumentElement(); } } diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java new file mode 100644 index 000000000..c5064da3f --- /dev/null +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java @@ -0,0 +1,82 @@ +/* + * 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.fo.extensions.svg; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.util.XMLResourceDescriptor; + +import org.apache.fop.svg.FOPSAXSVGDocumentFactory; +import org.apache.fop.util.ContentHandlerFactory; + +/** + * ContentHandlerFactory which constructs ContentHandlers that build SVG DOM Documents. + */ +public class SVGDOMContentHandlerFactory implements ContentHandlerFactory { + + /** + * Default Constructor. + */ + public SVGDOMContentHandlerFactory() { + //nop + } + + /** {@inheritDoc} */ + public String[] getSupportedNamespaces() { + return new String[] {SVGDOMImplementation.SVG_NAMESPACE_URI}; + } + + /** {@inheritDoc} */ + public ContentHandler createContentHandler() throws SAXException { + return new Handler(); + } + + private static class Handler extends FOPSAXSVGDocumentFactory + implements ContentHandlerFactory.ObjectSource { + + private ObjectBuiltListener obListener; + + public Handler() throws SAXException { + super(XMLResourceDescriptor.getXMLParserClassName()); + } + + /** {@inheritDoc} */ + public Object getObject() { + return getDocument(); + } + + /** {@inheritDoc} */ + public void setObjectBuiltListener(ObjectBuiltListener listener) { + this.obListener = listener; + } + + /** {@inheritDoc} */ + public void endDocument() throws SAXException { + super.endDocument(); + if (obListener != null) { + obListener.notifyObjectBuilt(getObject()); + } + } + + } + +} diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java index a40b80190..917e8c0d8 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java @@ -20,35 +20,28 @@ package org.apache.fop.fo.extensions.svg; // FOP -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.util.ContentHandlerFactory; -import org.apache.fop.util.DOMBuilderContentHandlerFactory; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.net.URL; -import org.apache.batik.dom.svg.SVGOMDocument; -import org.apache.batik.dom.svg.SVGOMElement; -import org.apache.batik.dom.svg.SVGContext; -import org.apache.batik.dom.util.XMLSupport; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGDocument; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; -import org.apache.batik.bridge.UnitProcessor; -import org.apache.batik.util.SVGConstants; - -import org.w3c.dom.DOMImplementation; +import org.apache.batik.bridge.UnitProcessor; +import org.apache.batik.dom.svg.SVGContext; import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.dom.svg.SVGOMDocument; +import org.apache.batik.dom.svg.SVGOMElement; +import org.apache.batik.dom.util.XMLSupport; +import org.apache.batik.util.SVGConstants; -import java.net.URL; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; +import org.apache.fop.fo.FONode; +import org.apache.fop.util.ContentHandlerFactory; /** - * class representing the SVG root element - * for constructing an svg document. + * Class representing the SVG root element + * for constructing an SVG document. */ public class SVGElement extends SVGObj { @@ -61,21 +54,9 @@ public class SVGElement extends SVGObj { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public ContentHandlerFactory getContentHandlerFactory() { - return new DOMBuilderContentHandlerFactory(getNamespaceURI(), - SVGDOMImplementation.getDOMImplementation()); - } - - /** - * {@inheritDoc} - */ - public void processNode(String elementName, Locator locator, - Attributes attlist, PropertyList propertyList) throws FOPException { - super.processNode(elementName, locator, attlist, propertyList); - init(); + return new SVGDOMContentHandlerFactory(); } /** @@ -170,16 +151,6 @@ public class SVGElement extends SVGObj { return p2d; } - private void init() { - DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); - String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; - doc = impl.createDocument(svgNS, "svg", null); - - element = doc.getDocumentElement(); - - buildTopLevel(doc, element); - } - /** * Get the size of the SVG root element. * @param size the font size diff --git a/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java b/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java index 720795cb2..fce6ed2b6 100644 --- a/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java +++ b/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java @@ -21,6 +21,8 @@ package org.apache.fop.svg; import java.io.IOException; +import org.w3c.dom.Document; + import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -71,4 +73,13 @@ public class FOPSAXSVGDocumentFactory extends SAXSVGDocumentFactory { return super.resolveEntity(publicId, systemId); } + /** + * Returns the document built up by handling the incoming SAX events. This method will not + * return any instance for the first SAX events have been received. + * @return the DOM document + */ + public Document getDocument() { + return this.document; + } + } diff --git a/status.xml b/status.xml index 2a951cb42..1ea87e4c9 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,9 @@ + + Added support for SVG 1.2 functionality inside fo:instream-foreign-object. + Fixed a bug when combining break-before with a span change. -- cgit v1.2.3 From 252a61b0a4fb8f5356c183df29df71d7f9e1bf4d Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 21 Nov 2008 16:33:33 +0000 Subject: Fix for unit test failure in transcoder tests (NullPointerException): Have to pass the root PSGraphics2D to NativeTextHandler instead of the PSGenerator as this one hasn't been initialized in PSGraphics2D when the NativeTextHandler is built in AbstractPSTranscoder. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@719629 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/render/ps/AbstractPSTranscoder.java | 15 +++++++++------ src/java/org/apache/fop/render/ps/NativeTextHandler.java | 15 ++++++++------- src/java/org/apache/fop/render/ps/PSSVGHandler.java | 12 +++++++----- 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index 374b5a256..705515311 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -25,20 +25,23 @@ import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.w3c.dom.Document; +import org.w3c.dom.svg.SVGLength; + import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.ImageTranscoder; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontSetup; -import org.apache.fop.svg.AbstractFOPTranscoder; + import org.apache.xmlgraphics.java2d.TextHandler; import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; -import org.w3c.dom.Document; -import org.w3c.dom.svg.SVGLength; + +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontSetup; +import org.apache.fop.svg.AbstractFOPTranscoder; /** * This class enables to transcode an input to a PostScript document. @@ -99,7 +102,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { //TODO Do custom font configuration here somewhere/somehow FontSetup.setup(fontInfo); PSGenerator generator = graphics.getPSGenerator(); - graphics.setCustomTextHandler(new NativeTextHandler(generator, fontInfo)); + graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); } super.transcode(document, uri, output); diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 98addd19e..7cf59d519 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -24,13 +24,14 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.io.IOException; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.java2d.ps.PSTextHandler; +import org.apache.xmlgraphics.ps.PSGenerator; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.java2d.ps.PSTextHandler; -import org.apache.xmlgraphics.ps.PSGenerator; /** * Specialized TextHandler implementation that the PSGraphics2D class delegates to to paint text @@ -38,7 +39,7 @@ import org.apache.xmlgraphics.ps.PSGenerator; */ public class NativeTextHandler implements PSTextHandler { - private final PSGenerator gen; + private PSGraphics2D rootG2D; /** FontInfo containing all available fonts */ protected FontInfo fontInfo; @@ -60,8 +61,8 @@ public class NativeTextHandler implements PSTextHandler { * @param g2d the PSGraphics2D instance this instances is used by * @param fontInfo the FontInfo object with all available fonts */ - public NativeTextHandler(PSGenerator gen, FontInfo fontInfo) { - this.gen = gen; + public NativeTextHandler(PSGraphics2D g2d, FontInfo fontInfo) { + this.rootG2D = g2d; if (fontInfo != null) { this.fontInfo = fontInfo; } else { @@ -84,7 +85,7 @@ public class NativeTextHandler implements PSTextHandler { } private PSGenerator getPSGenerator() { - return this.gen; + return this.rootG2D.getPSGenerator(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index 2bc0f069b..1e65dfb98 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -24,12 +24,18 @@ import java.awt.geom.AffineTransform; import java.io.IOException; import java.util.Map; +import org.w3c.dom.Document; + import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; + import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; @@ -37,9 +43,6 @@ import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.ps.PSGenerator; -import org.w3c.dom.Document; /** * PostScript XML handler for SVG. Uses Apache Batik for SVG processing. @@ -259,9 +262,8 @@ public class PSSVGHandler extends AbstractGenericSVGHandler NativeTextHandler nativeTextHandler = null; BridgeContext ctx = new BridgeContext(ua); if (!strokeText) { - PSGenerator generator = graphics.getPSGenerator(); FontInfo fontInfo = psInfo.getFontInfo(); - nativeTextHandler = new NativeTextHandler(generator, fontInfo); + nativeTextHandler = new NativeTextHandler(graphics, fontInfo); graphics.setCustomTextHandler(nativeTextHandler); PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); ctx.setTextPainter(textPainter); -- cgit v1.2.3 From 2f8e166bfd7e1e958b94a4fa590a51dc80915b86 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 21 Nov 2008 17:24:32 +0000 Subject: Fixed possible ClassCastException that was caused by my earlier attempt to support SVG 1.2. Batik's SAXSVGDocumentFactory doesn't currently deal well with the case when namespaces are declared outside of its scope. Worked around that by doing the SVG version detection in FOP code. SVG12DOMImplementation is obtained by reflection in order to keep backwards compatilibility with earlier Batik versions that don't support SVG 1.2. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@719646 13f79535-47bb-0310-9956-ffa450edef68 --- .../svg/SVGDOMContentHandlerFactory.java | 83 ++++++++++++++++++++-- .../apache/fop/fo/extensions/svg/SVGElement.java | 7 +- 2 files changed, 79 insertions(+), 11 deletions(-) (limited to 'src/java') diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java index c5064da3f..6556c7251 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java @@ -19,25 +19,37 @@ package org.apache.fop.fo.extensions.svg; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.batik.dom.svg.SVGDOMImplementation; -import org.apache.batik.util.XMLResourceDescriptor; -import org.apache.fop.svg.FOPSAXSVGDocumentFactory; import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.DelegatingContentHandler; /** - * ContentHandlerFactory which constructs ContentHandlers that build SVG DOM Documents. + * ContentHandlerFactory which constructs ContentHandlers that build SVG DOM + * Documents. */ public class SVGDOMContentHandlerFactory implements ContentHandlerFactory { + private static SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + /** * Default Constructor. */ public SVGDOMContentHandlerFactory() { - //nop + // nop } /** {@inheritDoc} */ @@ -50,13 +62,18 @@ public class SVGDOMContentHandlerFactory implements ContentHandlerFactory { return new Handler(); } - private static class Handler extends FOPSAXSVGDocumentFactory - implements ContentHandlerFactory.ObjectSource { + private static class Handler extends DelegatingContentHandler implements + ContentHandlerFactory.ObjectSource { + private Document doc; private ObjectBuiltListener obListener; public Handler() throws SAXException { - super(XMLResourceDescriptor.getXMLParserClassName()); + super(); + } + + public Document getDocument() { + return this.doc; } /** {@inheritDoc} */ @@ -69,6 +86,58 @@ public class SVGDOMContentHandlerFactory implements ContentHandlerFactory { this.obListener = listener; } + /** {@inheritDoc} */ + public void startDocument() throws SAXException { + // Suppress startDocument() call if doc has not been set, yet. It + // will be done later. + if (doc != null) { + super.startDocument(); + } + } + + private DOMImplementation getDOMImplementation(String ver) { + //TODO It would be great if Batik provided this method as static helper method. + if (ver == null || ver.length() == 0 + || ver.equals("1.0") || ver.equals("1.1")) { + return SVGDOMImplementation.getDOMImplementation(); + } else if (ver.equals("1.2")) { + try { + Class clazz = Class.forName( + "org.apache.batik.dom.svg12.SVG12DOMImplementation"); + return (DOMImplementation)clazz.getMethod( + "getDOMImplementation", null).invoke(null, null); + } catch (Exception e) { + return SVGDOMImplementation.getDOMImplementation(); + } + } + throw new RuntimeException("Unsupport SVG version '" + ver + "'"); + } + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, Attributes atts) + throws SAXException { + if (doc == null) { + TransformerHandler handler; + try { + handler = tFactory.newTransformerHandler(); + } catch (TransformerConfigurationException e) { + throw new SAXException("Error creating a new TransformerHandler", e); + } + String version = atts.getValue("version"); + DOMImplementation domImplementation = getDOMImplementation(version); + doc = domImplementation.createDocument(uri, qName, null); + // It's easier to work with an empty document, so remove the + // root element + doc.removeChild(doc.getDocumentElement()); + handler.setResult(new DOMResult(doc)); + setDelegateContentHandler(handler); + setDelegateLexicalHandler(handler); + setDelegateDTDHandler(handler); + handler.startDocument(); + } + super.startElement(uri, localName, qName, atts); + } + /** {@inheritDoc} */ public void endDocument() throws SAXException { super.endDocument(); diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java index 917e8c0d8..72cf19bc7 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java @@ -26,7 +26,6 @@ import java.awt.geom.Rectangle2D; import java.net.URL; import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.dom.svg.SVGContext; @@ -85,7 +84,6 @@ public class SVGElement extends SVGObj { log.error("Could not set base URL for svg", e); } - Element e = ((SVGDocument)doc).getRootElement(); final float ptmm = getUserAgent().getSourcePixelUnitToMillimeter(); // temporary svg context SVGContext dc = new SVGContext() { @@ -138,7 +136,8 @@ public class SVGElement extends SVGObj { public void deselectAll() { } }; - ((SVGOMElement)e).setSVGContext(dc); + SVGOMElement e = (SVGOMElement)svgRoot; + e.setSVGContext(dc); //if (!e.hasAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns")) { e.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns", @@ -146,7 +145,7 @@ public class SVGElement extends SVGObj { //} int fontSize = 12; Point2D p2d = getSize(fontSize, svgRoot, getUserAgent().getSourcePixelUnitToMillimeter()); - ((SVGOMElement)e).setSVGContext(null); + e.setSVGContext(null); return p2d; } -- cgit v1.2.3