diff options
author | Adrian Cumiskey <acumiskey@apache.org> | 2008-10-22 13:42:56 +0000 |
---|---|---|
committer | Adrian Cumiskey <acumiskey@apache.org> | 2008-10-22 13:42:56 +0000 |
commit | 82f8cd4c3a02919eb554776059f051623e2ac683 (patch) | |
tree | 8bc5cf28cf041ec50f840f5bfdfc907cc1fcce38 /src/java | |
parent | 69e12c0a1cec260629c5034abb609beb671bf09b (diff) | |
download | xmlgraphics-fop-82f8cd4c3a02919eb554776059f051623e2ac683.tar.gz xmlgraphics-fop-82f8cd4c3a02919eb554776059f051623e2ac683.zip |
Default to inline resource level for GOCA graphic objects (when no afp:resource-level extension is provided).
This is due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) (hard copy works just fine with default print-file level)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@707075 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
17 files changed, 1381 insertions, 8 deletions
diff --git a/src/java/org/apache/fop/fonts/CachedFontInfo.java.pres b/src/java/org/apache/fop/fonts/CachedFontInfo.java.pres new file mode 100644 index 000000000..7e698af6a --- /dev/null +++ b/src/java/org/apache/fop/fonts/CachedFontInfo.java.pres @@ -0,0 +1,114 @@ +/* + * 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.fonts; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import org.apache.commons.io.FileUtils; + +/** + * Font info stored in the cache + */ +public class CachedFontInfo extends EmbedFontInfo { + + /** Serialization Version UID */ + private static final long serialVersionUID = 240028291961081894L; + + /** file modify date (if available) */ + private long lastModified = -1; + + /** + * Returns a file given a list of urls + * @param urls array of possible font urls + * @return file font file + */ + public static File getFileFromUrls(String[] urls) { + for (int i = 0; i < urls.length; i++) { + try { + URL url = new URL(urls[i]); + url.getFile(); + File fontFile = FileUtils.toFile(url); + if (fontFile.exists() && fontFile.canRead()) { + return fontFile; + } + } catch (IllegalArgumentException e) { + // do nothing + } catch (MalformedURLException e) { + // do nothing + } + } + return null; + } + + /** + * Default constructor + * @param metricsFile metrics file + * @param kerning kerning + * @param fontTriplets font triplets + * @param embedFile embed file + * @param lastModified timestamp that this font was last modified + */ + public CachedFontInfo(String metricsFile, boolean kerning, List fontTriplets, + String embedFile, long lastModified) { + super(metricsFile, kerning, fontTriplets, embedFile); + this.lastModified = lastModified; + } + + /** + * Constructor + * @param fontInfo an existing embed font info + */ + public CachedFontInfo(EmbedFontInfo fontInfo) { + super(fontInfo.metricsFile, fontInfo.kerning, fontInfo.fontTriplets, fontInfo.embedFile); + // try and determine modified date + File fontFile = getFileFromUrls(new String[] {embedFile, metricsFile}); + if (fontFile != null ) { + this.lastModified = fontFile.lastModified(); + } + } + + /** + * Gets the modified timestamp for font file (not always available) + * @return modified timestamp + */ + public long lastModified() { + return this.lastModified; + } + + /** + * Gets the modified timestamp for font file + * (used for the purposes of font info caching) + * @param lastModified modified font file timestamp + */ + public void setLastModified(long lastModified) { + this.lastModified = lastModified; + } + + /** + * @return string representation of this object + * {@inheritDoc} + */ + public String toString() { + return super.toString() + ", lastModified=" + lastModified; + } +} diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index d9f2e0de8..ad838708d 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -206,7 +206,8 @@ public class FontInfo { private FontTriplet fontLookup(String family, String style, int weight, boolean substitutable) { if (log.isTraceEnabled()) { - log.trace("Font lookup: " + family + " " + style + " " + weight); + log.trace("Font lookup: " + family + " " + style + " " + weight + + (substitutable ? " substitutable" : "")); } FontTriplet startKey = createFontKey(family, style, weight); @@ -288,7 +289,7 @@ public class FontInfo { } // last resort: use default - if (internalFontKey == null) { + if (key == null && internalFontKey == null) { key = Font.DEFAULT_FONT; internalFontKey = getInternalFontKey(key); } @@ -359,7 +360,7 @@ public class FontInfo { private List/*<FontTriplet>*/ fontLookup(String[] families, String style, int weight, boolean substitutable) { - List matchingTriplets = new java.util.ArrayList(); + List/*<FontTriplet>*/ matchingTriplets = new java.util.ArrayList/*<FontTriplet>*/(); FontTriplet triplet = null; for (int i = 0; i < families.length; i++) { triplet = fontLookup(families[i], style, weight, substitutable); @@ -569,7 +570,7 @@ public class FontInfo { List/*<FontTriplet>*/ foundTriplets = new java.util.ArrayList(); for (Iterator iter = triplets.entrySet().iterator(); iter.hasNext();) { Map.Entry tripletEntry = (Map.Entry) iter.next(); - if (fontName.equals(((String)tripletEntry.getValue()))) { + if (fontName.equals((tripletEntry.getValue()))) { foundTriplets.add(tripletEntry.getKey()); } } diff --git a/src/java/org/apache/fop/fonts/svn-commit.2.tmp b/src/java/org/apache/fop/fonts/svn-commit.2.tmp new file mode 100644 index 000000000..9492437ed --- /dev/null +++ b/src/java/org/apache/fop/fonts/svn-commit.2.tmp @@ -0,0 +1,4 @@ +Url is actually a Uri +--This line, and those below, will be ignored-- + +M FontLoader.java diff --git a/src/java/org/apache/fop/fonts/svn-commit.tmp b/src/java/org/apache/fop/fonts/svn-commit.tmp new file mode 100644 index 000000000..d0cb89ebd --- /dev/null +++ b/src/java/org/apache/fop/fonts/svn-commit.tmp @@ -0,0 +1,4 @@ +Url is really a Uri +--This line, and those below, will be ignored-- + +M FontLoader.java diff --git a/src/java/org/apache/fop/fonts/type1/PFMFile.java.pres b/src/java/org/apache/fop/fonts/type1/PFMFile.java.pres new file mode 100644 index 000000000..f888cf050 --- /dev/null +++ b/src/java/org/apache/fop/fonts/type1/PFMFile.java.pres @@ -0,0 +1,490 @@ +/* + * 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: PFMFile.java 595297 2007-11-15 13:28:58Z jeremias $ */ + +package org.apache.fop.fonts.type1; + +// Java +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.fonts.Glyphs; + +/** + * This class represents a PFM file (or parts of it) as a Java object. + */ +public class PFMFile { + + // Header stuff + private String windowsName; + private String postscriptName; + private short dfItalic; + private int dfWeight; + private short dfCharSet; + private short dfPitchAndFamily; + private int dfAvgWidth; + private int dfMaxWidth; + private int dfMinWidth; + private short dfFirstChar; + private short dfLastChar; + + // Extension stuff + // --- + + // Extend Text Metrics + private int etmCapHeight; + private int etmXHeight; + private int etmLowerCaseAscent; + private int etmLowerCaseDescent; + + // Extent table + private int[] extentTable; + + private Map kerningTab = new java.util.HashMap(); + + /** + * logging instance + */ + protected Log log = LogFactory.getLog(PFMFile.class); + + /** + * Parses a PFM file + * + * @param inStream The stream from which to read the PFM file. + * @throws IOException In case of an I/O problem + */ + public void load(InputStream inStream) throws IOException { + byte[] pfmBytes = IOUtils.toByteArray(inStream); + InputStream bufin = inStream; + bufin = new ByteArrayInputStream(pfmBytes); + PFMInputStream in = new PFMInputStream(bufin); + bufin.mark(512); + short sh1 = in.readByte(); + short sh2 = in.readByte(); + if (sh1 == 128 && sh2 == 1) { + //Found the first section header of a PFB file! + throw new IOException("Cannot parse PFM file. You probably specified the PFB file" + + " of a Type 1 font as parameter instead of the PFM."); + } + bufin.reset(); + byte[] b = new byte[16]; + bufin.read(b); + if (new String(b, "US-ASCII").equalsIgnoreCase("StartFontMetrics")) { + //Found the header of a AFM file! + throw new IOException("Cannot parse PFM file. You probably specified the AFM file" + + " of a Type 1 font as parameter instead of the PFM."); + } + bufin.reset(); + final int version = in.readShort(); + if (version != 256) { + log.warn("PFM version expected to be '256' but got '" + version + "'." + + " Please make sure you specify the PFM as parameter" + + " and not the PFB or the AFM."); + } + //final long filesize = in.readInt(); + bufin.reset(); + + loadHeader(in); + loadExtension(in); + } + + /** + * Parses the header of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + * @throws IOException In case of an I/O problem + */ + private void loadHeader(PFMInputStream inStream) throws IOException { + inStream.skip(80); + dfItalic = inStream.readByte(); + inStream.skip(2); + dfWeight = inStream.readShort(); + dfCharSet = inStream.readByte(); + inStream.skip(4); + dfPitchAndFamily = inStream.readByte(); + dfAvgWidth = inStream.readShort(); + dfMaxWidth = inStream.readShort(); + dfFirstChar = inStream.readByte(); + dfLastChar = inStream.readByte(); + inStream.skip(8); + long faceOffset = inStream.readInt(); + + inStream.reset(); + inStream.skip(faceOffset); + windowsName = inStream.readString(); + + inStream.reset(); + inStream.skip(117); + } + + /** + * Parses the extension part of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadExtension(PFMInputStream inStream) throws IOException { + final int size = inStream.readShort(); + if (size != 30) { + log.warn("Size of extension block was expected to be " + + "30 bytes, but was " + size + " bytes."); + } + final long extMetricsOffset = inStream.readInt(); + final long extentTableOffset = inStream.readInt(); + inStream.skip(4); //Skip dfOriginTable + final long kernPairOffset = inStream.readInt(); + inStream.skip(4); //Skip dfTrackKernTable + long driverInfoOffset = inStream.readInt(); + + if (kernPairOffset > 0) { + inStream.reset(); + inStream.skip(kernPairOffset); + loadKernPairs(inStream); + } + + inStream.reset(); + inStream.skip(driverInfoOffset); + postscriptName = inStream.readString(); + + if (extMetricsOffset != 0) { + inStream.reset(); + inStream.skip(extMetricsOffset); + loadExtMetrics(inStream); + } + if (extentTableOffset != 0) { + inStream.reset(); + inStream.skip(extentTableOffset); + loadExtentTable(inStream); + } + + } + + /** + * Parses the kernPairs part of the pfm file + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadKernPairs(PFMInputStream inStream) throws IOException { + int i = inStream.readShort(); + + + if (log.isTraceEnabled()) { + log.trace(i + " kerning pairs"); + } + while (i > 0) { + int g1 = (int)inStream.readByte(); + i--; + + int g2 = (int)inStream.readByte(); + + int adj = inStream.readShort(); + if (adj > 0x8000) { + adj = -(0x10000 - adj); + } + + if (log.isTraceEnabled()) { + log.trace("Char no: (" + g1 + ", " + g2 + ") kern: " + adj); + final String glyph1 = Glyphs.TEX8R_GLYPH_NAMES[g1]; + final String glyph2 = Glyphs.TEX8R_GLYPH_NAMES[g2]; + log.trace("glyphs: " + glyph1 + ", " + glyph2); + } + + Map adjTab = (Map)kerningTab.get(new Integer(g1)); + if (adjTab == null) { + adjTab = new java.util.HashMap(); + } + adjTab.put(new Integer(g2), new Integer(adj)); + kerningTab.put(new Integer(g1), adjTab); + } + } + + /** + * Parses the extended metrics part of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadExtMetrics(PFMInputStream inStream) throws IOException { + final int size = inStream.readShort(); + if (size != 52) { + log.warn("Size of extension block was expected to be " + + "52 bytes, but was " + size + " bytes."); + } + inStream.skip(12); //Skip etmPointSize, etmOrientation, etmMasterHeight, + //etmMinScale, etmMaxScale, emtMasterUnits + etmCapHeight = inStream.readShort(); + etmXHeight = inStream.readShort(); + etmLowerCaseAscent = inStream.readShort(); + etmLowerCaseDescent = -(inStream.readShort()); + //Ignore the rest of the values + } + + /** + * Parses the extent table of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadExtentTable(PFMInputStream inStream) throws IOException { + extentTable = new int[dfLastChar - dfFirstChar + 1]; + dfMinWidth = dfMaxWidth; + for (short i = dfFirstChar; i <= dfLastChar; i++) { + extentTable[i - dfFirstChar] = inStream.readShort(); + if (extentTable[i - dfFirstChar] < dfMinWidth) { + dfMinWidth = extentTable[i - dfFirstChar]; + } + } + } + + /** + * Returns the Windows name of the font. + * + * @return The Windows name. + */ + public String getWindowsName() { + return windowsName; + } + + /** + * Return the kerning table. The kerning table is a Map with + * strings with glyphnames as keys, containing Maps as value. + * The value map contains a glyph name string key and an Integer value + * + * @return A Map containing the kerning table + */ + public Map getKerning() { + return kerningTab; + } + + /** + * Returns the Postscript name of the font. + * + * @return The Postscript name. + */ + public String getPostscriptName() { + return postscriptName; + } + + /** + * Returns the charset used for the font. + * + * @return The charset (0=WinAnsi). + */ + public short getCharSet() { + return dfCharSet; + } + + /** + * Returns the charset of the font as a string. + * + * @return The name of the charset. + */ + public String getCharSetName() { + //TODO Had to remove the detection for Expert(Subset) encoding. The PFM is not suitable + //for detecting these character sets. We have to parse the AFM for that. + switch (dfCharSet) { + case 0: + return "WinAnsi"; // AKA ISOAdobe + case 1: + return "Expert"; + case 2: + if ("Symbol".equals(getPostscriptName())) { + return "Symbol"; + } else { + return "ExpertSubset"; + } + case 128: + return "Shift-JIS (Japanese)"; + default: + log.warn("Unknown charset detected (" + dfCharSet + + ", 0x" + Integer.toHexString(dfCharSet) + + "). Trying fallback to WinAnsi."); + } + return "WinAnsi"; + } + + /** + * Returns the number of the character that defines + * the first entry in the widths list. + * + * @return The number of the first character. + */ + public short getFirstChar() { + return dfFirstChar; + } + + /** + * Returns the number of the character that defines + * the last entry in the widths list. + * + * @return The number of the last character. + */ + public short getLastChar() { + return dfLastChar; + } + + /** + * Returns the CapHeight parameter for the font (height of uppercase H). + * + * @return The CapHeight parameter. + */ + public int getCapHeight() { + return etmCapHeight; + } + + /** + * Returns the XHeight parameter for the font (height of lowercase x). + * + * @return The CapHeight parameter. + */ + public int getXHeight() { + return etmXHeight; + } + + /** + * Returns the LowerCaseAscent parameter for the font (height of lowercase d). + * + * @return The LowerCaseAscent parameter. + */ + public int getLowerCaseAscent() { + return etmLowerCaseAscent; + } + + /** + * Returns the LowerCaseDescent parameter for the font (height of lowercase p). + * + * @return The LowerCaseDescent parameter. + */ + public int getLowerCaseDescent() { + return etmLowerCaseDescent; + } + + /** + * Tells whether the font has proportional character spacing. + * + * @return ex. true for Times, false for Courier. + */ + public boolean getIsProportional() { + return ((dfPitchAndFamily & 1) == 1); + } + + /** + * Returns the bounding box for the font. + * Note: this value is just an approximation, + * it does not really exist in the PFM file. + * + * @return The calculated Font BBox. + */ + public int[] getFontBBox() { + int[] bbox = new int[4]; + + // Just guessing.... + if (!getIsProportional() && (dfAvgWidth == dfMaxWidth)) { + bbox[0] = -20; + } else { + bbox[0] = -100; + } + bbox[1] = getLowerCaseDescent() - 5; + bbox[2] = dfMaxWidth + 10; + bbox[3] = getLowerCaseAscent() + 5; + return bbox; + } + + /** + * Indicates whether the font is non-symbolic (Font uses the Adobe standard Latin character + * set or a subset of it). + * @return true if the font is non-symbolic + */ + public boolean isNonSymbolic() { + return (dfCharSet != 2); //!= Symbol fonts + } + + /** + * Returns the characteristics flags for the font as + * needed for a PDF font descriptor (See PDF specs). + * + * @return The characteristics flags. + */ + public int getFlags() { + int flags = 0; + if (!getIsProportional()) { + flags |= 1; //bit 1: FixedPitch + } + if (isNonSymbolic()) { + flags |= 32; //bit 6: Nonsymbolic + } else { + flags |= 4; //bit 3: Symbolic + } + //int serif = dfPitchAndFamily & 0xFFFE; + if ((dfPitchAndFamily & 16) != 0) { + flags |= 2; //bit 2: Serif + } + if ((dfPitchAndFamily & 64) != 0) { + flags |= 8; //bit 4: Script + } + if (dfItalic != 0) { + flags |= 64; //bit 7: Italic + } + return flags; + } + + /** + * Returns the width of the dominant vertical stems of the font. + * Note: this value is just an approximation, + * it does not really exist in the PFM file. + * + * @return The vertical stem width. + */ + public int getStemV() { + // Just guessing.... + if (dfItalic != 0) { + return (int)Math.round(dfMinWidth * 0.25); + } else { + return (int)Math.round(dfMinWidth * 0.6); + } + } + + /** + * Returns the italic angle of the font. + * Note: this value is just an approximation, + * it does not really exist in the PFM file. + * + * @return The italic angle. + */ + public int getItalicAngle() { + if (dfItalic != 0) { + return -16; // Just guessing.... + } else { + return 0; + } + } + + /** + * Returns the width of a character + * + * @param which The number of the character for which the width is requested. + * @return The width of a character. + */ + public int getCharWidth(short which) { + return extentTable[which - dfFirstChar]; + } + +} diff --git a/src/java/org/apache/fop/image/TIFFImage.java.pres b/src/java/org/apache/fop/image/TIFFImage.java.pres new file mode 100644 index 000000000..703692cf5 --- /dev/null +++ b/src/java/org/apache/fop/image/TIFFImage.java.pres @@ -0,0 +1,216 @@ +/* + * 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: TIFFImage.java 557337 2007-07-18 17:37:14Z adelmelle $ */ + +package org.apache.fop.image; + +import java.awt.color.ColorSpace; +import java.io.IOException; + +import org.apache.xmlgraphics.image.codec.util.SeekableStream; +import org.apache.xmlgraphics.image.codec.tiff.TIFFDirectory; +import org.apache.xmlgraphics.image.codec.tiff.TIFFField; +import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder; +import org.apache.xmlgraphics.image.rendered.CachableRed; +import org.apache.commons.io.IOUtils; + +/** + * TIFF implementation using the Batik codecs. + */ +public class TIFFImage extends XmlGraphicsCommonsImage { + + private int compression = 0; + private int stripCount = 0; + private long stripOffset = 0; + private long stripLength = 0; + private int fillOrder = 1; + + /** + * Constructs a new BatikImage instance. + * @param imgReader basic metadata for the image + */ + public TIFFImage(FopImage.ImageInfo imgReader) { + super(imgReader); + } + + /** + * The compression type set in the TIFF directory + * @return the TIFF compression type + */ + public int getCompression() { + return compression; + } + + /** + * The number of strips in the image + * @return the number of strips in the image + */ + public int getStripCount() { + return stripCount; + } + + /** + * {@inheritDoc} + * org.apache.xmlgraphics.image.codec.util.SeekableStream) + */ + protected CachableRed decodeImage(SeekableStream stream) throws IOException { + org.apache.xmlgraphics.image.codec.tiff.TIFFImage img + = new org.apache.xmlgraphics.image.codec.tiff.TIFFImage + (stream, null, 0); + TIFFDirectory dir = (TIFFDirectory)img.getProperty("tiff_directory"); + TIFFField fld = dir.getField(TIFFImageDecoder.TIFF_X_RESOLUTION); + if (fld != null) { + log.debug("x resolution = " + fld.getAsDouble(0)); + this.dpiHorizontal = fld.getAsDouble(0); + } else { + log.warn("Cannot determine x resolution."); + } + fld = dir.getField(TIFFImageDecoder.TIFF_Y_RESOLUTION); + if (fld != null) { + log.debug("y resolution = " + fld.getAsDouble(0)); + this.dpiVertical = fld.getAsDouble(0); + } else { + log.warn("Cannot determine y resolution."); + } + fld = dir.getField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT); + if (fld != null) { + int resUnit = fld.getAsInt(0); + if (resUnit == 3) { + //cm + this.dpiHorizontal *= 2.54f; + this.dpiVertical *= 2.54f; + } else if (resUnit != 2) { + //ignored + log.warn("Cannot determine bitmap resolution." + + " Unimplemented resolution unit: " + resUnit); + } + } else { + log.warn("Cannot determine bitmap resolution unit."); + } + fld = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION); + if (fld != null) { + compression = fld.getAsInt(0); + } + fld = dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE); + if (fld != null) { + bitsPerPixel = fld.getAsInt(0); + } + fld = dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP); + if (fld == null) { + stripCount = 1; + } else { + stripCount = (int)(dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH) + / fld.getAsLong(0)); + } + + fld = dir.getField(TIFFImageDecoder.TIFF_FILL_ORDER); + if (fld != null) { + fillOrder = fld.getAsInt(0); + } + + stripOffset = dir.getField(TIFFImageDecoder.TIFF_STRIP_OFFSETS).getAsLong(0); + stripLength = dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS).getAsLong(0); + + if (this.bitsPerPixel == 1) { + this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY); + } + return img; + } + + /** + * Load the original TIFF data. + * This loads only strip 1 of the original TIFF data. + * + * @return true if loaded false for any error + * {@inheritDoc} + */ + protected boolean loadOriginalData() { + if (loadDimensions()) { + byte[] readBuf = new byte[(int)stripLength]; + int bytesRead; + + try { + this.seekableInput.reset(); + this.seekableInput.skip(stripOffset); + bytesRead = seekableInput.read(readBuf); + if (bytesRead != stripLength) { + log.error("Error while loading image: length mismatch on read"); + return false; + } + + // need to invert bytes if fill order = 2 + if (fillOrder == 2) { + for (int i = 0; i < (int)stripLength; i++) { + readBuf[i] = flipTable[readBuf[i] & 0xff]; + } + } + this.raw = readBuf; + + return true; + } catch (IOException ioe) { + log.error("Error while loading image strip 1 (TIFF): ", ioe); + return false; + } finally { + IOUtils.closeQuietly(seekableInput); + IOUtils.closeQuietly(inputStream); + this.seekableInput = null; + this.inputStream = null; + this.cr = null; + } + } + return false; + } + + // Table to be used when fillOrder = 2, for flipping bytes. + // Copied from XML Graphics Commons' TIFFFaxDecoder class + private static byte[] flipTable = { + 0, -128, 64, -64, 32, -96, 96, -32, + 16, -112, 80, -48, 48, -80, 112, -16, + 8, -120, 72, -56, 40, -88, 104, -24, + 24, -104, 88, -40, 56, -72, 120, -8, + 4, -124, 68, -60, 36, -92, 100, -28, + 20, -108, 84, -44, 52, -76, 116, -12, + 12, -116, 76, -52, 44, -84, 108, -20, + 28, -100, 92, -36, 60, -68, 124, -4, + 2, -126, 66, -62, 34, -94, 98, -30, + 18, -110, 82, -46, 50, -78, 114, -14, + 10, -118, 74, -54, 42, -86, 106, -22, + 26, -102, 90, -38, 58, -70, 122, -6, + 6, -122, 70, -58, 38, -90, 102, -26, + 22, -106, 86, -42, 54, -74, 118, -10, + 14, -114, 78, -50, 46, -82, 110, -18, + 30, -98, 94, -34, 62, -66, 126, -2, + 1, -127, 65, -63, 33, -95, 97, -31, + 17, -111, 81, -47, 49, -79, 113, -15, + 9, -119, 73, -55, 41, -87, 105, -23, + 25, -103, 89, -39, 57, -71, 121, -7, + 5, -123, 69, -59, 37, -91, 101, -27, + 21, -107, 85, -43, 53, -75, 117, -11, + 13, -115, 77, -51, 45, -83, 109, -19, + 29, -99, 93, -35, 61, -67, 125, -3, + 3, -125, 67, -61, 35, -93, 99, -29, + 19, -109, 83, -45, 51, -77, 115, -13, + 11, -117, 75, -53, 43, -85, 107, -21, + 27, -101, 91, -37, 59, -69, 123, -5, + 7, -121, 71, -57, 39, -89, 103, -25, + 23, -105, 87, -41, 55, -73, 119, -9, + 15, -113, 79, -49, 47, -81, 111, -17, + 31, -97, 95, -33, 63, -65, 127, -1, + }; + // end +} diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index c29dbea15..9e977cd80 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -28,11 +28,8 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -import org.w3c.dom.Document; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; @@ -68,6 +65,7 @@ import org.apache.fop.area.inline.WordArea; import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; +import org.w3c.dom.Document; /** * Abstract base class for all renderers. The Abstract renderer does all the @@ -504,7 +502,7 @@ public abstract class AbstractRenderer */ protected void renderBlocks(Block parent, List blocks) { int saveIP = currentIPPosition; - int saveBP = currentBPPosition; +// int saveBP = currentBPPosition; // Calculate the position of the content rectangle. if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { diff --git a/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java b/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java index 2febe7171..ab9cf7ef7 100644 --- a/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java +++ b/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java @@ -51,11 +51,20 @@ public class AFPImageGraphics2DFactory extends AFPDataObjectInfoFactory { return new AFPGraphicsObjectInfo(); } + private static final AFPResourceLevel inlineResourceLevel = new AFPResourceLevel(AFPResourceLevel.INLINE); + /** {@inheritDoc} */ public AFPDataObjectInfo create(AFPImageInfo afpImageInfo) throws IOException { AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo)super.create(afpImageInfo); + AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo(); + // level not explicitly set/changed so default to inline for GOCA graphic objects + // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) - hard copy works just fine) + if (!resourceInfo.levelChanged()) { + resourceInfo.setLevel(inlineResourceLevel); + } + // set mime type (unsupported by MOD:CA registry) graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA); diff --git a/src/java/org/apache/fop/render/afp/AFPResourceInfo.java b/src/java/org/apache/fop/render/afp/AFPResourceInfo.java index cdb7c0961..f52a3cd0b 100644 --- a/src/java/org/apache/fop/render/afp/AFPResourceInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPResourceInfo.java @@ -35,6 +35,9 @@ public class AFPResourceInfo { /** the resource level of this resource */ private AFPResourceLevel level = DEFAULT_LEVEL; + /** true when the resource level was changed */ + private boolean levelChanged = false; + /** * Sets the data object uri * @@ -90,6 +93,16 @@ public class AFPResourceInfo { */ public void setLevel(AFPResourceLevel resourceLevel) { this.level = resourceLevel; + levelChanged = true; + } + + /** + * Returns true when the resource level was set + * + * @return true when the resource level was set + */ + public boolean levelChanged() { + return levelChanged; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPResourceInfo.java b/src/java/org/apache/fop/render/afp/extensions/AFPResourceInfo.java new file mode 100644 index 000000000..66d9555d6 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/extensions/AFPResourceInfo.java @@ -0,0 +1,188 @@ +/* + * 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.render.afp.extensions; + +import org.xml.sax.helpers.AttributesImpl; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +//import org.xml.sax.helpers.AttributesImpl; + +/** + * An AFP resource group configuration definition for a document + */ +public class AFPResourceInfo extends AFPExtensionAttachment { + private static final long serialVersionUID = -7333967815112216396L; + + /** AFP resource groups are stored in an external resource file */ + private static final int LEVEL_INLINE = 0; + + /** AFP resource groups are stored at page level */ + private static final int LEVEL_PAGE = 1; + + /** AFP resource groups are stored at page group level */ + private static final int LEVEL_PAGE_GROUP = 2; + + /** AFP resource groups are stored within the document at document level */ + private static final int LEVEL_DOCUMENT = 3; + + /** AFP resource groups are stored outside the document at print file level */ + private static final int LEVEL_PRINT_FILE = 4; + + /** AFP resource groups are stored in an external resource file */ + private static final int LEVEL_EXTERNAL = 5; + + + private static final String LEVEL_NAME_INLINE = "inline"; + + private static final String LEVEL_NAME_PAGE = "page"; + + private static final String LEVEL_NAME_PAGE_GROUP = "page-group"; + + private static final String LEVEL_NAME_DOCUMENT = "document"; + + private static final String LEVEL_NAME_PRINT_FILE = "print-file"; + + private static final String LEVEL_NAME_EXTERNAL = "external"; + + + /** + * level token/name mapping + */ + private static final String[] LEVEL_NAME_MAP = { + LEVEL_NAME_INLINE, LEVEL_NAME_PAGE, LEVEL_NAME_PAGE_GROUP, + LEVEL_NAME_DOCUMENT, LEVEL_NAME_PRINT_FILE, LEVEL_NAME_EXTERNAL + }; + + /** + * the <afp:resource-info/> element name + */ + public static final String ELEMENT = "resource-info"; + + /** + * the level at which resource groups are placed + */ + private int level = -1; + + /** + * the destination filename for resource groups with level = "external" + */ + private String dest; + + /** + * Default constructor. + */ + public AFPResourceInfo() { + super(ELEMENT); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "AFPResourceInfo(" + + "name=" + name + ", " + + (level > -1 ? "level=" + LEVEL_NAME_MAP[level] : "") + + (dest != null ? ", dest=" + getDestination() : "" ) + ")"; + } + + /** + * Sets the destination filename of where resources + * are to be stored for this document + * @param destination the location of the external resource group file + */ + public void setExternalDestination(String destination) { + this.dest = destination; + } + + /** + * Returns the destination filename of where external resources + * are to be stored for this document. + * @return the destination AFP external resource filename + */ + public String getDestination() { + return this.dest; + } + + /** + * Sets the level at which resource groups are stored + * @param level the resource group level + */ + public void setLevel(int level) { + this.level = level; + } + + /** + * Sets the level at which resource groups are stored + * @param name the level name + */ + public void setLevel(String name) { + if (name != null) { + for (int i = 0; i < LEVEL_NAME_MAP.length; i++) { + if (name.toLowerCase().equals(LEVEL_NAME_MAP[i])) { + this.level = i; + } + } + } + } + + /** + * Returns the level at which resource groups are stored + * @return the level at which resource groups are stored + */ + public int getLevel() { + return this.level; + } + + private static final String ATT_LEVEL = "level"; + + private static final String ATT_DEST = "dest"; + + /** + * {@inheritDoc} + */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + + // name + if (hasName()) { + atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", super.getName()); + } + + // level + if (level > 0) { + atts.addAttribute(null, ATT_LEVEL, ATT_LEVEL, "CDATA", LEVEL_NAME_MAP[level]); + + // dest + if (level == LEVEL_EXTERNAL && dest != null && dest.length() > 0) { + atts.addAttribute(null, ATT_DEST, ATT_DEST, "CDATA", dest); + } + } + handler.startElement(CATEGORY, elementName, elementName, atts); + handler.endElement(CATEGORY, elementName, elementName); + } + + /** + * @return true if this resource group is to be stored externally + */ + public boolean isExternalLevel() { + return level == LEVEL_EXTERNAL; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPResourceInfoElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPResourceInfoElement.java new file mode 100644 index 000000000..7613e80ae --- /dev/null +++ b/src/java/org/apache/fop/render/afp/extensions/AFPResourceInfoElement.java @@ -0,0 +1,93 @@ +/* + * 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.render.afp.extensions; + +import org.apache.fop.apps.FOPException; +//import org.apache.fop.fo.Constants; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; +//import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.fo.PropertyList; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +/** + * Extension element for afp:resource-group + */ +public class AFPResourceInfoElement extends AbstractAFPExtensionObject { + + /** + * Main constructor + * @param parent parent FO node + */ + public AFPResourceInfoElement(FONode parent) { + super(parent, AFPResourceInfo.ELEMENT); + } + + /** + * @throws FOPException if there's a problem during processing + * @see org.apache.fop.fo.FONode#startOfNode() + */ + protected void startOfNode() throws FOPException { + if (parent.getNameId() != Constants.FO_INSTREAM_FOREIGN_OBJECT + && parent.getNameId() != Constants.FO_EXTERNAL_GRAPHIC) { + invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), + "rule.childOfInstreamForeignObjectorExternalGraphic"); + } + } + + /** + * {@inheritDoc} + */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList propertyList) + throws FOPException { + getExtensionAttachment(); + String attr = attlist.getValue("name"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setName(attr); + } else { + throw new FOPException(elementName + " must have a name attribute."); + } + String lvl = attlist.getValue("level"); + AFPResourceInfo resourceInfo = (AFPResourceInfo)getExtensionAttachment(); + if (lvl != null && lvl.length() > 0) { + resourceInfo.setLevel(lvl); + if (resourceInfo.isExternalLevel()) { + String dest = attlist.getValue("dest"); + if (dest != null && dest.length() > 0) { + resourceInfo.setExternalDestination(dest); + } else { + throw new FOPException("must have a dest attribute."); + } + } + } else { + throw new FOPException("must have a level attribute."); + } + } + + /** + * {@inheritDoc} + */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPResourceInfo(); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/goca/GraphicsSetMix.java b/src/java/org/apache/fop/render/afp/goca/GraphicsSetMix.java new file mode 100644 index 000000000..99a04d3ee --- /dev/null +++ b/src/java/org/apache/fop/render/afp/goca/GraphicsSetMix.java @@ -0,0 +1,55 @@ +/* + * 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.render.afp.goca; + +import org.apache.fop.render.afp.modca.AbstractPreparedAFPObject; + +public class GraphicsSetMix extends AbstractPreparedAFPObject { + + public static final byte MODE_DEFAULT = 0x00; + public static final byte MODE_OVERPAINT = 0x02; + + /** the mix mode value */ + private final byte mode; + + /** + * Main constructor + * + * @param mode the mix mode value + */ + public GraphicsSetMix(byte mode) { + this.mode = mode; + prepareData(); + } + + /** {@inheritDoc} */ + protected void prepareData() { + super.data = new byte[] { + 0x0C, // GSMX order code + mode // MODE (mix mode value) + }; + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetMix{mode=" + mode + "}"; + } + +} diff --git a/src/java/org/apache/fop/render/afp/modca/DocumentIndex.java b/src/java/org/apache/fop/render/afp/modca/DocumentIndex.java new file mode 100644 index 000000000..5b3350b91 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/DocumentIndex.java @@ -0,0 +1,69 @@ +/* + * 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.render.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + * The document index defined by the MOD:CA architecture provides functions + * for indexing the document based on document structure and on + * application-defined document tags. + */ +public class DocumentIndex extends AbstractStructuredAFPObject { + /** + * document index element + */ + private IndexElement indexElement; + + private List linkLogicalElements; + + private List tagLogicalElements; + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + indexElement.writeToStream(os); + writeObjects(linkLogicalElements, os); + writeObjects(tagLogicalElements, os); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + } + + + private class IndexElement extends AbstractAFPObject { + + public void writeToStream(OutputStream os) throws IOException { + } + + } +} diff --git a/src/java/org/apache/fop/render/afp/svn-commit.2.tmp b/src/java/org/apache/fop/render/afp/svn-commit.2.tmp new file mode 100644 index 000000000..986ccd6ae --- /dev/null +++ b/src/java/org/apache/fop/render/afp/svn-commit.2.tmp @@ -0,0 +1,25 @@ +Moved goca package to level above modca. +--This line, and those below, will be ignored-- + +A goca +A goca/GraphicsChainedSegment.java +A goca/GraphicsSetPatternSymbol.java +A goca/GraphicsFillet.java +A goca/GraphicsSetCurrentPosition.java +D goca/AbstractPreparedAFPObject.java +A goca/GraphicsSetCharacterSet.java +A goca/GraphicsImageBegin.java +A goca/GraphicsLine.java +A goca/GraphicsBox.java +A goca/GraphicsFullArc.java +A goca/GraphicsSetProcessColor.java +A goca/AbstractGraphicsCoord.java +A goca/GraphicsSetLineWidth.java +A goca/GraphicsSetLineType.java +A goca/GraphicsSetArcParameters.java +A goca/AbstractGraphicsContainer.java +A goca/GraphicsString.java +A goca/GraphicsArea.java +A goca/GraphicsImageEnd.java +A goca/GraphicsData.java +A goca/GraphicsImageData.java diff --git a/src/java/org/apache/fop/render/afp/svn-commit.3.tmp b/src/java/org/apache/fop/render/afp/svn-commit.3.tmp new file mode 100644 index 000000000..986ccd6ae --- /dev/null +++ b/src/java/org/apache/fop/render/afp/svn-commit.3.tmp @@ -0,0 +1,25 @@ +Moved goca package to level above modca. +--This line, and those below, will be ignored-- + +A goca +A goca/GraphicsChainedSegment.java +A goca/GraphicsSetPatternSymbol.java +A goca/GraphicsFillet.java +A goca/GraphicsSetCurrentPosition.java +D goca/AbstractPreparedAFPObject.java +A goca/GraphicsSetCharacterSet.java +A goca/GraphicsImageBegin.java +A goca/GraphicsLine.java +A goca/GraphicsBox.java +A goca/GraphicsFullArc.java +A goca/GraphicsSetProcessColor.java +A goca/AbstractGraphicsCoord.java +A goca/GraphicsSetLineWidth.java +A goca/GraphicsSetLineType.java +A goca/GraphicsSetArcParameters.java +A goca/AbstractGraphicsContainer.java +A goca/GraphicsString.java +A goca/GraphicsArea.java +A goca/GraphicsImageEnd.java +A goca/GraphicsData.java +A goca/GraphicsImageData.java diff --git a/src/java/org/apache/fop/render/afp/svn-commit.tmp b/src/java/org/apache/fop/render/afp/svn-commit.tmp new file mode 100644 index 000000000..986ccd6ae --- /dev/null +++ b/src/java/org/apache/fop/render/afp/svn-commit.tmp @@ -0,0 +1,25 @@ +Moved goca package to level above modca. +--This line, and those below, will be ignored-- + +A goca +A goca/GraphicsChainedSegment.java +A goca/GraphicsSetPatternSymbol.java +A goca/GraphicsFillet.java +A goca/GraphicsSetCurrentPosition.java +D goca/AbstractPreparedAFPObject.java +A goca/GraphicsSetCharacterSet.java +A goca/GraphicsImageBegin.java +A goca/GraphicsLine.java +A goca/GraphicsBox.java +A goca/GraphicsFullArc.java +A goca/GraphicsSetProcessColor.java +A goca/AbstractGraphicsCoord.java +A goca/GraphicsSetLineWidth.java +A goca/GraphicsSetLineType.java +A goca/GraphicsSetArcParameters.java +A goca/AbstractGraphicsContainer.java +A goca/GraphicsString.java +A goca/GraphicsArea.java +A goca/GraphicsImageEnd.java +A goca/GraphicsData.java +A goca/GraphicsImageData.java diff --git a/src/java/org/apache/fop/svg/patch.diff b/src/java/org/apache/fop/svg/patch.diff new file mode 100644 index 000000000..649a735ab --- /dev/null +++ b/src/java/org/apache/fop/svg/patch.diff @@ -0,0 +1,44 @@ +Index: PDFGraphics2D.java +=================================================================== +--- PDFGraphics2D.java (Revision 570024) ++++ PDFGraphics2D.java (Arbeitskopie) +@@ -719,13 +719,15 @@ + } + + c = getColor(); +- if (graphicsState.setColor(c)) { ++ graphicsState.setColor(c); ++ // if (graphicsState.setColor(c)) { + applyColor(c, false); +- } ++ // } + c = getBackground(); +- if (graphicsState.setBackColor(c)) { ++ graphicsState.setBackColor(c); ++ // if (graphicsState.setBackColor(c)) { + applyColor(c, true); +- } ++ // } + + Paint paint = getPaint(); + if (graphicsState.setPaint(paint)) { +@@ -1718,13 +1720,15 @@ + } + + c = getColor(); +- if (graphicsState.setColor(c)) { ++ graphicsState.setColor(c); ++ // if (graphicsState.setColor(c)) { + applyColor(c, true); +- } ++ // } + c = getBackground(); +- if (graphicsState.setBackColor(c)) { ++ graphicsState.setBackColor(c); ++ // if (graphicsState.setBackColor(c)) { + applyColor(c, false); +- } ++ // } + + Paint paint = getPaint(); + if (graphicsState.setPaint(paint)) { |