You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by lb...@apache.org on 2013/11/13 16:24:27 UTC
svn commit: r1541551 [1/3] - in /xmlgraphics/fop/trunk: ./ lib/
src/java/org/apache/fop/pdf/ src/java/org/apache/fop/render/ps/
src/java/org/apache/fop/render/ps/svg/
src/java/org/apache/fop/render/shading/ src/java/org/apache/fop/svg/
test/java/org/ap...
Author: lbernardo
Date: Wed Nov 13 15:24:26 2013
New Revision: 1541551
URL: http://svn.apache.org/r1541551
Log:
FOP-2313: add support for svg gradients when generating PostScript; most code authored by Robert Meyer with a small contribution by Athanasios Giannimaras.
Added:
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSShading.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/Function.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/FunctionDelegate.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/FunctionPattern.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/GradientFactory.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/GradientRegistrar.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/PDFGradientFactory.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/PSGradientFactory.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/Pattern.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/Shading.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/ShadingPattern.java (with props)
xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/
xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/PSSVGGraphics2DTestCase.java (with props)
xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/PSSVGLinearGraphics2DTestCase.java (with props)
xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/axial-shading-expected.dat
xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/expected.ps
Modified:
xmlgraphics/fop/trunk/build.xml
xmlgraphics/fop/trunk/lib/xmlgraphics-commons-svn-trunk.jar
xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java
Modified: xmlgraphics/fop/trunk/build.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/build.xml?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/build.xml (original)
+++ xmlgraphics/fop/trunk/build.xml Wed Nov 13 15:24:26 2013
@@ -579,6 +579,7 @@ list of possible build targets.
<include name="org/apache/fop/util/Finalizable.class"/>
<include name="org/apache/fop/util/CharUtilities.class"/>
<include name="org/apache/fop/util/DecimalFormatCache*.class"/>
+ <include name="org/apache/fop/render/shading/**"/>
</patternset>
<!-- PDF transcoder -->
<patternset>
Modified: xmlgraphics/fop/trunk/lib/xmlgraphics-commons-svn-trunk.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/lib/xmlgraphics-commons-svn-trunk.jar?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
Binary files - no diff available.
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java Wed Nov 13 15:24:26 2013
@@ -310,12 +310,7 @@ public class PDFFactory {
theFunctionDataStream,
theFilter);
- PDFFunction oldfunc = getDocument().findFunction(function);
- if (oldfunc == null) {
- getDocument().registerObject(function);
- } else {
- function = oldfunc;
- }
+ function = registerFunction(function);
return (function);
}
@@ -352,12 +347,7 @@ public class PDFFactory {
PDFFunction function = new PDFFunction(theFunctionType, theDomain,
theRange, theCZero, theCOne,
theInterpolationExponentN);
- PDFFunction oldfunc = getDocument().findFunction(function);
- if (oldfunc == null) {
- getDocument().registerObject(function);
- } else {
- function = oldfunc;
- }
+ function = registerFunction(function);
return (function);
}
@@ -407,12 +397,7 @@ public class PDFFactory {
theRange, theFunctions,
theBounds, theEncode);
- PDFFunction oldfunc = getDocument().findFunction(function);
- if (oldfunc == null) {
- getDocument().registerObject(function);
- } else {
- function = oldfunc;
- }
+ function = registerFunction(function);
return (function);
}
@@ -434,14 +419,23 @@ public class PDFFactory {
theRange,
theFunctionDataStream);
+ function = registerFunction(function);
+ return (function);
+
+ }
+
+ /**
+ * Registers a function against the document
+ * @param function The function to register
+ */
+ public PDFFunction registerFunction(PDFFunction function) {
PDFFunction oldfunc = getDocument().findFunction(function);
if (oldfunc == null) {
getDocument().registerObject(function);
} else {
function = oldfunc;
}
- return (function);
-
+ return function;
}
/* ========================= shadings ================================== */
@@ -481,20 +475,7 @@ public class PDFFactory {
theBBox, theAntiAlias, theDomain,
theMatrix, theFunction);
- PDFShading oldshad = getDocument().findShading(shading);
- if (oldshad == null) {
- getDocument().registerObject(shading);
- } else {
- shading = oldshad;
- }
-
- // add this shading to resources
- if (res != null) {
- res.getPDFResources().addShading(shading);
- } else {
- getDocument().getResources().addShading(shading);
- }
-
+ shading = registerShading(res, shading);
return (shading);
}
@@ -534,18 +515,7 @@ public class PDFFactory {
theDomain, theFunction,
theExtend);
- PDFShading oldshad = getDocument().findShading(shading);
- if (oldshad == null) {
- getDocument().registerObject(shading);
- } else {
- shading = oldshad;
- }
-
- if (res != null) {
- res.getPDFResources().addShading(shading);
- } else {
- getDocument().getResources().addShading(shading);
- }
+ shading = registerShading(res, shading);
return (shading);
}
@@ -591,18 +561,7 @@ public class PDFFactory {
theBitsPerFlag, theDecode,
theFunction);
- PDFShading oldshad = getDocument().findShading(shading);
- if (oldshad == null) {
- getDocument().registerObject(shading);
- } else {
- shading = oldshad;
- }
-
- if (res != null) {
- res.getPDFResources().addShading(shading);
- } else {
- getDocument().getResources().addShading(shading);
- }
+ shading = registerShading(res, shading);
return (shading);
}
@@ -645,6 +604,17 @@ public class PDFFactory {
theBitsPerComponent, theDecode,
theVerticesPerRow, theFunction);
+ shading = registerShading(res, shading);
+
+ return (shading);
+ }
+
+ /**
+ * Registers a shading object against the document
+ * @param res The PDF resource context
+ * @param shading The shading object to be registered
+ */
+ public PDFShading registerShading(PDFResourceContext res, PDFShading shading) {
PDFShading oldshad = getDocument().findShading(shading);
if (oldshad == null) {
getDocument().registerObject(shading);
@@ -652,13 +622,13 @@ public class PDFFactory {
shading = oldshad;
}
+ // add this shading to resources
if (res != null) {
res.getPDFResources().addShading(shading);
} else {
getDocument().getResources().addShading(shading);
}
-
- return (shading);
+ return shading;
}
/* ========================= patterns ================================== */
@@ -707,6 +677,22 @@ public class PDFFactory {
return (pattern);
}
+ public PDFPattern registerPattern(PDFResourceContext res, PDFPattern pattern) {
+ PDFPattern oldpatt = getDocument().findPattern(pattern);
+ if (oldpatt == null) {
+ getDocument().registerObject(pattern);
+ } else {
+ pattern = oldpatt;
+ }
+
+ if (res != null) {
+ res.getPDFResources().addPattern(pattern);
+ } else {
+ getDocument().getResources().addPattern(pattern);
+ }
+ return pattern;
+ }
+
/**
* Make a smooth shading pattern
*
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java Wed Nov 13 15:24:26 2013
@@ -22,6 +22,10 @@ package org.apache.fop.pdf;
// Java...
import java.util.List;
+import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.shading.FunctionDelegate;
+import org.apache.fop.render.shading.FunctionPattern;
+
/**
* class representing a PDF Function.
*
@@ -33,126 +37,9 @@ import java.util.List;
*
* All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
*/
-public class PDFFunction extends PDFObject {
- // Guts common to all function types
-
- /**
- * Required: The Type of function (0,2,3,4) default is 0.
- */
- protected int functionType = 0; // Default
-
- /**
- * Required: 2 * m Array of Double numbers which are possible inputs to the function
- */
- protected List domain = null;
-
- /**
- * Required: 2 * n Array of Double numbers which are possible outputs to the function
- */
- protected List range = null;
-
- /* ********************TYPE 0***************************** */
- // FunctionType 0 specific function guts
-
- /**
- * Required: Array containing the Integer size of the Domain and Range, respectively.
- * Note: This is really more like two seperate integers, sizeDomain, and sizeRange,
- * but since they're expressed as an array in PDF, my implementation reflects that.
- */
- protected List size = null;
-
- /**
- * Required for Type 0: Number of Bits used to represent each sample value.
- * Limited to 1,2,4,8,12,16,24, or 32
- */
- protected int bitsPerSample = 1;
-
- /**
- * Optional for Type 0: order of interpolation between samples.
- * Limited to linear (1) or cubic (3). Default is 1
- */
- protected int order = 1;
-
- /**
- * Optional for Type 0: A 2 * m array of Doubles which provides a
- * linear mapping of input values to the domain.
- *
- * Required for Type 3: A 2 * k array of Doubles that, taken
- * in pairs, map each subset of the domain defined by Domain
- * and the Bounds array to the domain of the corresponding function.
- * Should be two values per function, usually (0,1),
- * as in [0 1 0 1] for 2 functions.
- */
- protected List encode = null;
+public class PDFFunction extends PDFObject implements Function {
- /**
- * Optional for Type 0: A 2 * n array of Doubles which provides
- * a linear mapping of sample values to the range. Defaults to Range.
- */
- protected List decode = null;
-
- /**
- * Optional For Type 0: A stream of sample values
- */
-
- /**
- * Required For Type 4: Postscript Calculator function
- * composed of arithmetic, boolean, and stack operators + boolean constants
- */
- protected StringBuffer functionDataStream = null;
-
- /**
- * Required (possibly) For Type 0: A vector of Strings for the
- * various filters to be used to decode the stream.
- * These are how the string is compressed. Flate, LZW, etc.
- */
- protected List filter = null;
- /* *************************TYPE 2************************** */
-
- /**
- * Required For Type 2: An Array of n Doubles defining
- * the function result when x=0. Default is [0].
- */
- protected List cZero = null;
-
- /**
- * Required For Type 2: An Array of n Doubles defining
- * the function result when x=1. Default is [1].
- */
- protected List cOne = null;
-
- /**
- * Required for Type 2: The interpolation exponent.
- * Each value x will return n results.
- * Must be greater than 0.
- */
- protected double interpolationExponentN = 1;
-
- /* *************************TYPE 3************************** */
-
- /**
- * Required for Type 3: An vector of PDFFunctions which
- * form an array of k single input functions making up
- * the stitching function.
- */
- protected List functions = null;
-
- /**
- * Optional for Type 3: An array of (k-1) Doubles that,
- * in combination with Domain, define the intervals to which
- * each function from the Functions array apply. Bounds
- * elements must be in order of increasing magnitude,
- * and each value must be within the value of Domain.
- * k is the number of functions.
- * If you pass null, it will output (1/k) in an array of k-1 elements.
- * This makes each function responsible for an equal amount of the stitching function.
- * It makes the gradient even.
- */
- protected List bounds = null;
- // See encode above, as it's also part of Type 3 Functions.
-
- /* *************************TYPE 4************************** */
- // See 'data' above.
+ private FunctionDelegate delegate;
/**
* create an complete Function object of Type 0, A Sampled function.
@@ -211,26 +98,13 @@ public class PDFFunction extends PDFObje
* @param theFunctionType This is the type of function (0,2,3, or 4).
* It should be 0 as this is the constructor for sampled functions.
*/
- public PDFFunction(int theFunctionType, List theDomain,
- List theRange, List theSize, int theBitsPerSample,
- int theOrder, List theEncode, List theDecode,
- StringBuffer theFunctionDataStream, List theFilter) {
- super();
-
- this.functionType = 0; // dang well better be 0;
- this.size = theSize;
- this.bitsPerSample = theBitsPerSample;
- this.order = theOrder; // int
- this.encode = theEncode; // vector of int
- this.decode = theDecode; // vector of int
- this.functionDataStream = theFunctionDataStream;
- this.filter = theFilter; // vector of Strings
-
- // the domain and range are actually two dimensional arrays.
- // so if there's not an even number of items, bad stuff
- // happens.
- this.domain = theDomain;
- this.range = theRange;
+ public PDFFunction(int theFunctionType, List<Double> theDomain,
+ List<Double> theRange, List<Double> theSize, int theBitsPerSample,
+ int theOrder, List<Double> theEncode, List<Double> theDecode,
+ StringBuffer theFunctionDataStream, List<String> theFilter) {
+ delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+ theSize, theBitsPerSample, theOrder, theEncode, theDecode,
+ theFunctionDataStream, theFilter);
}
/**
@@ -260,20 +134,11 @@ public class PDFFunction extends PDFObje
* PDF Spec page 268
* @param theFunctionType The type of the function, which should be 2.
*/
- public PDFFunction(int theFunctionType, List theDomain,
- List theRange, List theCZero, List theCOne,
+ public PDFFunction(int theFunctionType, List<Double> theDomain,
+ List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
double theInterpolationExponentN) {
- super();
-
- this.functionType = 2; // dang well better be 2;
-
- this.cZero = theCZero;
- this.cOne = theCOne;
- this.interpolationExponentN = theInterpolationExponentN;
-
-
- this.domain = theDomain;
- this.range = theRange;
+ delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+ theCZero, theCOne, theInterpolationExponentN);
}
@@ -312,18 +177,11 @@ public class PDFFunction extends PDFObje
* @param theFunctionType This is the function type. It should be 3,
* for a stitching function.
*/
- public PDFFunction(int theFunctionType, List theDomain,
- List theRange, List theFunctions,
- List theBounds, List theEncode) {
- super();
-
- this.functionType = 3; // dang well better be 3;
-
- this.functions = theFunctions;
- this.bounds = theBounds;
- this.encode = theEncode;
- this.domain = theDomain;
- this.range = theRange;
+ public PDFFunction(int theFunctionType, List<Double> theDomain,
+ List<Double> theRange, List<Function> theFunctions,
+ List<Double> theBounds, List<Double> theEncode) {
+ delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+ theFunctions, theBounds, theEncode);
}
@@ -349,20 +207,12 @@ public class PDFFunction extends PDFObje
* @param theFunctionType The type of function which should be 4, as this is
* a Postscript calculator function
*/
- public PDFFunction(int theFunctionType, List theDomain,
- List theRange, StringBuffer theFunctionDataStream) {
- super();
-
- this.functionType = 4; // dang well better be 4;
- this.functionDataStream = theFunctionDataStream;
-
- this.domain = theDomain;
-
- this.range = theRange;
-
+ public PDFFunction(int theFunctionType, List<Double> theDomain,
+ List<Double> theRange, StringBuffer theFunctionDataStream) {
+ delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+ theFunctionDataStream);
}
-
/**
* represent as PDF. Whatever the FunctionType is, the correct
* representation spits out. The sets of required and optional
@@ -375,319 +225,13 @@ public class PDFFunction extends PDFObje
* @return the PDF string.
*/
public byte[] toPDF() {
- int vectorSize = 0;
- int numberOfFunctions = 0;
- int tempInt = 0;
- StringBuffer p = new StringBuffer(256);
- p.append("<< \n/FunctionType " + this.functionType + " \n");
-
- // FunctionType 0
- if (this.functionType == 0) {
- if (this.domain != null) {
- // DOMAIN
- p.append("/Domain [ ");
- vectorSize = this.domain.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- // SIZE
- if (this.size != null) {
- p.append("/Size [ ");
- vectorSize = this.size.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.size.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
- // ENCODE
- if (this.encode != null) {
- p.append("/Encode [ ");
- vectorSize = this.encode.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.encode.get(tempInt))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Encode [ ");
- vectorSize = this.functions.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append("0 1 ");
- }
- p.append("] \n");
-
- }
-
- // BITSPERSAMPLE
- p.append("/BitsPerSample " + this.bitsPerSample);
-
- // ORDER (optional)
- if (this.order == 1 || this.order == 3) {
- p.append(" \n/Order " + this.order + " \n");
- }
-
- // RANGE
- if (this.range != null) {
- p.append("/Range [ ");
- vectorSize = this.range.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // DECODE
- if (this.decode != null) {
- p.append("/Decode [ ");
- vectorSize = this.decode.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.decode.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // LENGTH
- if (this.functionDataStream != null) {
- p.append("/Length " + (this.functionDataStream.length() + 1)
- + " \n");
- }
-
- // FILTER?
- if (this.filter != null) { // if there's a filter
- vectorSize = this.filter.size();
- p.append("/Filter ");
- if (vectorSize == 1) {
- p.append("/" + ((String)this.filter.get(0))
- + " \n");
- } else {
- p.append("[ ");
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append("/" + ((String)this.filter.get(0))
- + " ");
- }
- p.append("] \n");
- }
- }
- p.append(">>");
-
- // stream representing the function
- if (this.functionDataStream != null) {
- p.append("\nstream\n" + this.functionDataStream
- + "\nendstream");
- }
-
- // end of if FunctionType 0
-
- } else if (this.functionType == 2) {
- // DOMAIN
- if (this.domain != null) {
- p.append("/Domain [ ");
- vectorSize = this.domain.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
-
- // RANGE
- if (this.range != null) {
- p.append("/Range [ ");
- vectorSize = this.range.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // FunctionType, C0, C1, N are required in PDF
-
- // C0
- if (this.cZero != null) {
- p.append("/C0 [ ");
- vectorSize = this.cZero.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.cZero.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- // C1
- if (this.cOne != null) {
- p.append("/C1 [ ");
- vectorSize = this.cOne.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.cOne.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- // N: The interpolation Exponent
- p.append("/N "
- + PDFNumber.doubleOut(new Double(this.interpolationExponentN))
- + " \n");
-
- p.append(">>");
-
- } else if (this.functionType
- == 3) { // fix this up when my eyes uncross
- // DOMAIN
- if (this.domain != null) {
- p.append("/Domain [ ");
- vectorSize = this.domain.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- // RANGE
- if (this.range != null) {
- p.append("/Range [ ");
- vectorSize = this.range.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // FUNCTIONS
- if (this.functions != null) {
- p.append("/Functions [ ");
- numberOfFunctions = this.functions.size();
- for (tempInt = 0; tempInt < numberOfFunctions; tempInt++) {
- p.append(((PDFFunction)this.functions.get(tempInt)).referencePDF()
- + " ");
-
- }
- p.append("] \n");
- }
-
-
- // ENCODE
- if (this.encode != null) {
- p.append("/Encode [ ");
- vectorSize = this.encode.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.encode.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Encode [ ");
- vectorSize = this.functions.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append("0 1 ");
- }
- p.append("] \n");
-
- }
-
-
- // BOUNDS, required, but can be empty
- p.append("/Bounds [ ");
- if (this.bounds != null) {
-
- vectorSize = this.bounds.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.bounds.get(tempInt))
- + " ");
- }
-
- } else {
- if (this.functions != null) {
- // if there are n functions,
- // there must be n-1 bounds.
- // so let each function handle an equal portion
- // of the whole. e.g. if there are 4, then [ 0.25 0.25 0.25 ]
-
- String functionsFraction = PDFNumber.doubleOut(new Double(1.0
- / ((double)numberOfFunctions)));
-
- for (tempInt = 0; tempInt + 1 < numberOfFunctions;
- tempInt++) {
-
- p.append(functionsFraction + " ");
- }
- functionsFraction = null; // clean reference.
-
- }
-
- }
- p.append("]\n>>");
- } else if (this.functionType
- == 4) { // fix this up when my eyes uncross
- // DOMAIN
- if (this.domain != null) {
- p.append("/Domain [ ");
- vectorSize = this.domain.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- // RANGE
- if (this.range != null) {
- p.append("/Range [ ");
- vectorSize = this.range.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // LENGTH
- if (this.functionDataStream != null) {
- p.append("/Length " + (this.functionDataStream.length() + 1)
- + " \n");
- }
-
- p.append(">>");
-
- // stream representing the function
- if (this.functionDataStream != null) {
- p.append("\nstream\n{ " + this.functionDataStream
- + " }\nendstream");
- }
-
-
- }
+ return toByteString();
+ }
- return encode(p.toString());
+ public byte[] toByteString() {
+ FunctionPattern pattern = new FunctionPattern(this);
+ return encode(pattern.toWriteableString());
}
/** {@inheritDoc} */
@@ -702,96 +246,155 @@ public class PDFFunction extends PDFObje
return false;
}
PDFFunction func = (PDFFunction)obj;
- if (functionType != func.functionType) {
+ if (delegate.getFunctionType() != func.getFunctionType()) {
return false;
}
- if (bitsPerSample != func.bitsPerSample) {
+ if (delegate.getBitsPerSample() != func.getBitsPerSample()) {
return false;
}
- if (order != func.order) {
+ if (delegate.getOrder() != func.getOrder()) {
return false;
}
- if (interpolationExponentN != func.interpolationExponentN) {
+ if (delegate.getInterpolationExponentN() != func.getInterpolationExponentN()) {
return false;
}
- if (domain != null) {
- if (!domain.equals(func.domain)) {
+ if (delegate.getDomain() != null) {
+ if (!delegate.getDomain().equals(func.getDomain())) {
return false;
}
- } else if (func.domain != null) {
+ } else if (func.getDomain() != null) {
return false;
}
- if (range != null) {
- if (!range.equals(func.range)) {
+ if (delegate.getRange() != null) {
+ if (!delegate.getRange().equals(func.getRange())) {
return false;
}
- } else if (func.range != null) {
+ } else if (func.getRange() != null) {
return false;
}
- if (size != null) {
- if (!size.equals(func.size)) {
+ if (delegate.getSize() != null) {
+ if (!delegate.getSize().equals(func.getSize())) {
return false;
}
- } else if (func.size != null) {
+ } else if (func.getSize() != null) {
return false;
}
- if (encode != null) {
- if (!encode.equals(func.encode)) {
+ if (delegate.getEncode() != null) {
+ if (!delegate.getEncode().equals(func.getEncode())) {
return false;
}
- } else if (func.encode != null) {
+ } else if (func.getEncode() != null) {
return false;
}
- if (decode != null) {
- if (!decode.equals(func.decode)) {
+ if (delegate.getDecode() != null) {
+ if (!delegate.getDecode().equals(func.getDecode())) {
return false;
}
- } else if (func.decode != null) {
+ } else if (func.getDecode() != null) {
return false;
}
- if (functionDataStream != null) {
- if (!functionDataStream.equals(func.functionDataStream)) {
+ if (delegate.getDataStream() != null) {
+ if (!delegate.getDataStream().equals(func.getDataStream())) {
return false;
}
- } else if (func.functionDataStream != null) {
+ } else if (func.getDataStream() != null) {
return false;
}
- if (filter != null) {
- if (!filter.equals(func.filter)) {
+ if (delegate.getFilter() != null) {
+ if (!delegate.getFilter().equals(func.getFilter())) {
return false;
}
- } else if (func.filter != null) {
+ } else if (func.getFilter() != null) {
return false;
}
- if (cZero != null) {
- if (!cZero.equals(func.cZero)) {
+ if (delegate.getCZero() != null) {
+ if (!delegate.getCZero().equals(func.getCZero())) {
return false;
}
- } else if (func.cZero != null) {
+ } else if (func.getCZero() != null) {
return false;
}
- if (cOne != null) {
- if (!cOne.equals(func.cOne)) {
+ if (delegate.getCOne() != null) {
+ if (!delegate.getCOne().equals(func.getCOne())) {
return false;
}
- } else if (func.cOne != null) {
+ } else if (func.getCOne() != null) {
return false;
}
- if (functions != null) {
- if (!functions.equals(func.functions)) {
+ if (delegate.getFunctions() != null) {
+ if (!delegate.getFunctions().equals(func.getFunctions())) {
return false;
}
- } else if (func.functions != null) {
+ } else if (func.getFunctions() != null) {
return false;
}
- if (bounds != null) {
- if (!bounds.equals(func.bounds)) {
+ if (delegate.getBounds() != null) {
+ if (!delegate.getBounds().equals(func.getBounds())) {
return false;
}
- } else if (func.bounds != null) {
+ } else if (func.getBounds() != null) {
return false;
}
return true;
}
+ public int getFunctionType() {
+ return delegate.getFunctionType();
+ }
+
+ public List<Double> getBounds() {
+ return delegate.getBounds();
+ }
+
+ public List<Double> getDomain() {
+ return delegate.getDomain();
+ }
+
+ public List<Double> getSize() {
+ return delegate.getSize();
+ }
+
+ public List<String> getFilter() {
+ return delegate.getFilter();
+ }
+
+ public List<Double> getEncode() {
+ return delegate.getEncode();
+ }
+
+ public List<Function> getFunctions() {
+ return delegate.getFunctions();
+ }
+
+ public int getBitsPerSample() {
+ return delegate.getBitsPerSample();
+ }
+
+ public double getInterpolationExponentN() {
+ return delegate.getInterpolationExponentN();
+ }
+
+ public int getOrder() {
+ return delegate.getOrder();
+ }
+
+ public List<Double> getRange() {
+ return delegate.getRange();
+ }
+
+ public List<Double> getDecode() {
+ return delegate.getDecode();
+ }
+
+ public StringBuffer getDataStream() {
+ return delegate.getDataStream();
+ }
+
+ public List<Double> getCZero() {
+ return delegate.getCZero();
+ }
+
+ public List<Double> getCOne() {
+ return delegate.getCOne();
+ }
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java Wed Nov 13 15:24:26 2013
@@ -23,6 +23,9 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
+import org.apache.fop.render.shading.Pattern;
+import org.apache.fop.render.shading.Shading;
+
/**
* class representing a PDF Function.
*
@@ -33,7 +36,7 @@ import java.util.List;
*
* All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
*/
-public class PDFPattern extends PDFPathPaint {
+public class PDFPattern extends PDFPathPaint implements Pattern {
/**
* The resources associated with this pattern
@@ -146,13 +149,14 @@ public class PDFPattern extends PDFPathP
* @param theExtGState optional: the extended graphics state, if used.
* @param theMatrix Optional:List of Doubles that specify the matrix.
*/
- public PDFPattern(int thePatternType, PDFShading theShading,
+ public PDFPattern(int thePatternType, Shading theShading,
List theXUID, StringBuffer theExtGState,
List theMatrix) {
super();
this.patternType = 2; // thePatternType;
- this.shading = theShading;
+ assert theShading instanceof PDFShading;
+ this.shading = (PDFShading)theShading;
this.xUID = theXUID;
// this isn't really implemented, so it should always be null.
// I just don't want to have to add a new parameter once it is implemented.
@@ -259,7 +263,7 @@ public class PDFPattern extends PDFPathP
vectorSize = this.xUID.size();
p.append("/XUID [ ");
for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(((Integer)this.xUID.get(tempInt)) + " ");
+ p.append((this.xUID.get(tempInt)) + " ");
}
p.append("] \n");
}
@@ -290,7 +294,7 @@ public class PDFPattern extends PDFPathP
vectorSize = this.xUID.size();
p.append("/XUID [ ");
for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(((Integer)this.xUID.get(tempInt)) + " ");
+ p.append((this.xUID.get(tempInt)) + " ");
}
p.append("] \n");
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java Wed Nov 13 15:24:26 2013
@@ -22,6 +22,10 @@ package org.apache.fop.pdf;
// Java...
import java.util.List;
+import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.shading.Shading;
+import org.apache.fop.render.shading.ShadingPattern;
+
/**
* class representing a PDF Smooth Shading object.
*
@@ -32,7 +36,7 @@ import java.util.List;
*
* All PDF Functions have a shadingType (0,2,3, or 4), a Domain, and a Range.
*/
-public class PDFShading extends PDFObject {
+public class PDFShading extends PDFObject implements Shading {
// Guts common to all function types
/**
@@ -205,7 +209,7 @@ public class PDFShading extends PDFObjec
public PDFShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
List theBackground, List theBBox,
boolean theAntiAlias, List theCoords,
- List theDomain, PDFFunction theFunction,
+ List theDomain, Function theFunction,
List theExtend) {
super();
this.shadingType = theShadingType; // 2 or 3
@@ -216,7 +220,8 @@ public class PDFShading extends PDFObjec
this.coords = theCoords;
this.domain = theDomain;
- this.function = theFunction;
+ assert theFunction instanceof PDFFunction;
+ this.function = (PDFFunction)theFunction;
this.extend = theExtend;
}
@@ -335,197 +340,8 @@ public class PDFShading extends PDFObjec
* @return the PDF string.
*/
public String toPDFString() {
- int vectorSize;
- int tempInt;
- StringBuffer p = new StringBuffer(128);
- p.append("<<\n/ShadingType " + this.shadingType + " \n");
- if (this.colorSpace != null) {
- p.append("/ColorSpace /"
- + this.colorSpace.getName() + " \n");
- }
-
- if (this.background != null) {
- p.append("/Background [ ");
- vectorSize = this.background.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.background.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- if (this.bBox
- != null) { // I've never seen an example, so I guess this is right.
- p.append("/BBox [ ");
- vectorSize = this.bBox.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.bBox.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- if (this.antiAlias) {
- p.append("/AntiAlias " + this.antiAlias + " \n");
- }
-
- // Here's where we differentiate based on what type it is.
- if (this.shadingType == 1) { // function based shading
- if (this.domain != null) {
- p.append("/Domain [ ");
- vectorSize = this.domain.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- if (this.matrix != null) {
- p.append("/Matrix [ ");
- vectorSize = this.matrix.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.matrix.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
- } else if ((this.shadingType == 2)
- || (this.shadingType
- == 3)) { // 2 is axial shading (linear gradient)
- // 3 is radial shading (circular gradient)
- if (this.coords != null) {
- p.append("/Coords [ ");
- vectorSize = this.coords.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.coords.get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- // DOMAIN
- if (this.domain != null) {
- p.append("/Domain [ ");
- vectorSize = this.domain.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- if (this.extend != null) {
- p.append("/Extend [ ");
- vectorSize = this.extend.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(((Boolean)this.extend.get(tempInt)) + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Extend [ true true ] \n");
- }
-
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
-
-
- } else if ((this.shadingType == 4) || (this.shadingType == 6)
- || (this.shadingType
- == 7)) { // 4:Free-form Gouraud-shaded triangle meshes
- // 6:coons patch meshes
- // 7://tensor product patch meshes (which no one ever uses)
- if (this.bitsPerCoordinate > 0) {
- p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
- + " \n");
- } else {
- p.append("/BitsPerCoordinate 1 \n");
- }
-
- if (this.bitsPerComponent > 0) {
- p.append("/BitsPerComponent " + this.bitsPerComponent
- + " \n");
- } else {
- p.append("/BitsPerComponent 1 \n");
- }
-
- if (this.bitsPerFlag > 0) {
- p.append("/BitsPerFlag " + this.bitsPerFlag + " \n");
- } else {
- p.append("/BitsPerFlag 2 \n");
- }
-
- if (this.decode != null) {
- p.append("/Decode [ ");
- vectorSize = this.decode.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(((Boolean)this.decode.get(tempInt)) + " ");
- }
-
- p.append("] \n");
- }
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
-
- } else if (this.shadingType
- == 5) { // Lattice Free form gouraud-shaded triangle mesh
-
- if (this.bitsPerCoordinate > 0) {
- p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
- + " \n");
- } else {
- p.append("/BitsPerCoordinate 1 \n");
- }
-
- if (this.bitsPerComponent > 0) {
- p.append("/BitsPerComponent " + this.bitsPerComponent
- + " \n");
- } else {
- p.append("/BitsPerComponent 1 \n");
- }
-
- if (this.decode != null) {
- p.append("/Decode [ ");
- vectorSize = this.decode.size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(((Boolean)this.decode.get(tempInt)) + " ");
- }
-
- p.append("] \n");
- }
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
-
- if (this.verticesPerRow > 0) {
- p.append("/VerticesPerRow " + this.verticesPerRow + " \n");
- } else {
- p.append("/VerticesPerRow 2 \n");
- }
-
- }
-
- p.append(">>");
-
- return (p.toString());
+ ShadingPattern pattern = new ShadingPattern(this);
+ return pattern.toString(colorSpace, shadingType, background, bBox, antiAlias);
}
/** {@inheritDoc} */
@@ -623,4 +439,173 @@ public class PDFShading extends PDFObjec
}
return true;
}
+
+ /**
+ * A method to write a type 1 shading object
+ * @param p The StringBuffer to write the shading object
+ * @return Returns the StringBuffer to which the shading object was written
+ */
+ public StringBuffer handleShadingType1(StringBuffer p) {
+ if (this.domain != null) {
+ p.append("/Domain [ ");
+ for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
+ p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
+ + " ");
+ }
+ p.append("] \n");
+ } else {
+ p.append("/Domain [ 0 1 ] \n");
+ }
+
+ if (this.matrix != null) {
+ p.append("/Matrix [ ");
+ for (int matrixIndex = 0; matrixIndex < matrix.size(); matrixIndex++) {
+ p.append(PDFNumber.doubleOut((Double)this.matrix.get(matrixIndex))
+ + " ");
+ }
+ p.append("] \n");
+ }
+
+ if (this.function != null) {
+ p.append("/Function ");
+ p.append(this.function.referencePDF() + " \n");
+ }
+ return p;
+ }
+
+ /**
+ * A method to write a type 2 or 3 shading object
+ * @param p The StringBuffer to write the shading object
+ * @return Returns the StringBuffer to which the shading object was written
+ */
+ public StringBuffer handleShadingType2or3(StringBuffer p) {
+ // 3 is radial shading (circular gradient)
+ if (this.coords != null) {
+ p.append("/Coords [ ");
+ for (int coordIndex = 0; coordIndex < coords.size(); coordIndex++) {
+ p.append(PDFNumber.doubleOut((Double)this.coords.get(coordIndex))
+ + " ");
+ }
+ p.append("] \n");
+ }
+
+ // DOMAIN
+ if (this.domain != null) {
+ p.append("/Domain [ ");
+ for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
+ p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
+ + " ");
+ }
+ p.append("] \n");
+ } else {
+ p.append("/Domain [ 0 1 ] \n");
+ }
+
+ if (this.extend != null) {
+ p.append("/Extend [ ");
+ for (int extendIndex = 0; extendIndex < extend.size(); extendIndex++) {
+ p.append((this.extend.get(extendIndex)) + " ");
+ }
+
+ p.append("] \n");
+ } else {
+ p.append("/Extend [ true true ] \n");
+ }
+
+
+ if (this.function != null) {
+ p.append("/Function ");
+ p.append(this.function.referencePDF() + " \n");
+ }
+
+ return p;
+ }
+
+ /**
+ * A method to write a type 4, 6 or 7 shading object
+ * @param p The StringBuffer to write the shading object
+ * @return Returns the StringBuffer to which the shading object was written
+ */
+ public StringBuffer handleShadingType4or6or7(StringBuffer p) {
+ // 6:coons patch meshes
+ // 7://tensor product patch meshes (which no one ever uses)
+ if (this.bitsPerCoordinate > 0) {
+ p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
+ + " \n");
+ } else {
+ p.append("/BitsPerCoordinate 1 \n");
+ }
+
+ if (this.bitsPerComponent > 0) {
+ p.append("/BitsPerComponent " + this.bitsPerComponent
+ + " \n");
+ } else {
+ p.append("/BitsPerComponent 1 \n");
+ }
+
+ if (this.bitsPerFlag > 0) {
+ p.append("/BitsPerFlag " + this.bitsPerFlag + " \n");
+ } else {
+ p.append("/BitsPerFlag 2 \n");
+ }
+
+ if (this.decode != null) {
+ p.append("/Decode [ ");
+ for (int decodeIndex = 0; decodeIndex < decode.size(); decodeIndex++) {
+ p.append((this.decode.get(decodeIndex)) + " ");
+ }
+
+ p.append("] \n");
+ }
+
+ if (this.function != null) {
+ p.append("/Function ");
+ p.append(this.function.referencePDF() + " \n");
+ }
+
+ return p;
+ }
+
+ /**
+ * A method to write a type 5 shading object
+ * @param p The StringBuffer to write the shading object
+ * @return Returns the StringBuffer to which the shading object was written
+ */
+ public StringBuffer handleShadingType5(StringBuffer p) {
+ if (this.bitsPerCoordinate > 0) {
+ p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
+ + " \n");
+ } else {
+ p.append("/BitsPerCoordinate 1 \n");
+ }
+
+ if (this.bitsPerComponent > 0) {
+ p.append("/BitsPerComponent " + this.bitsPerComponent
+ + " \n");
+ } else {
+ p.append("/BitsPerComponent 1 \n");
+ }
+
+ if (this.decode != null) {
+ p.append("/Decode [ ");
+ for (int decodeIndex = 0; decodeIndex < decode.size(); decodeIndex++) {
+ p.append((this.decode.get(decodeIndex)) + " ");
+ }
+
+ p.append("] \n");
+ }
+
+ if (this.function != null) {
+ p.append("/Function ");
+ p.append(this.function.referencePDF() + " \n");
+ }
+
+ if (this.verticesPerRow > 0) {
+ p.append("/VerticesPerRow " + this.verticesPerRow + " \n");
+ } else {
+ p.append("/VerticesPerRow 2 \n");
+ }
+
+ return p;
+ }
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java Wed Nov 13 15:24:26 2013
@@ -19,26 +19,50 @@
package org.apache.fop.render.ps;
+import java.awt.Color;
+import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.imageio.ImageIO;
import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.transcoder.SVGAbstractTranscoder;
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderInput;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
-import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
+import org.apache.xmlgraphics.ps.ImageEncoder;
+import org.apache.xmlgraphics.ps.ImageEncodingHelper;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.fop.image.loader.batik.BatikImageFlavors;
import org.apache.fop.image.loader.batik.BatikUtil;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.ps.svg.PSSVGGraphics2D;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
@@ -47,6 +71,9 @@ import org.apache.fop.svg.SVGUserAgent;
*/
public class PSImageHandlerSVG implements ImageHandler {
+ private static final Color FALLBACK_COLOR = new Color(255, 33, 117);
+ private HashMap<String, String> gradientsFound = new HashMap<String, String>();
+
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
BatikImageFlavors.SVG_DOM
};
@@ -58,78 +85,262 @@ public class PSImageHandlerSVG implement
PSGenerator gen = psContext.getGenerator();
ImageXMLDOM imageSVG = (ImageXMLDOM)image;
- //Controls whether text painted by Batik is generated using text or path operations
- boolean strokeText = false;
- //TODO Configure text stroking
-
- SVGUserAgent ua
- = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
-
- PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
- graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
-
- BridgeContext ctx = new PSBridgeContext(ua,
- (strokeText ? null : psContext.getFontInfo()),
- context.getUserAgent().getImageManager(),
- context.getUserAgent().getImageSessionContext());
-
- //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
- //to it.
- Document clonedDoc = BatikUtil.cloneSVGDocument(imageSVG.getDocument());
+ if (shouldRaster(imageSVG)) {
+ InputStream is = renderSVGToInputStream(context, imageSVG);
- GraphicsNode root;
+ float x = (float) pos.getX() / 1000f;
+ float y = (float) pos.getY() / 1000f;
+ float w = (float) pos.getWidth() / 1000f;
+ float h = (float) pos.getHeight() / 1000f;
+ Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
+
+ MaskedImage mi = convertToRGB(ImageIO.read(is));
+ BufferedImage ri = mi.getImage();
+ ImageEncoder encoder = ImageEncodingHelper.createRenderedImageEncoder(ri);
+ Dimension imgDim = new Dimension(ri.getWidth(), ri.getHeight());
+ String imgDescription = ri.getClass().getName();
+ ImageEncodingHelper helper = new ImageEncodingHelper(ri);
+ ColorModel cm = helper.getEncodedColorModel();
+ PSImageUtils.writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen, ri, mi.getMaskColor());
+ } else {
+ //Controls whether text painted by Batik is generated using text or path operations
+ boolean strokeText = false;
+ //TODO Configure text stroking
+
+ SVGUserAgent ua
+ = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
+
+ PSSVGGraphics2D graphics = new PSSVGGraphics2D(strokeText, gen);
+ graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+
+ BridgeContext ctx = new PSBridgeContext(ua,
+ (strokeText ? null : psContext.getFontInfo()),
+ context.getUserAgent().getImageManager(),
+ context.getUserAgent().getImageSessionContext());
+
+ //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+ //to it.
+ Document clonedDoc = BatikUtil.cloneSVGDocument(imageSVG.getDocument());
+
+ GraphicsNode root;
+ try {
+ GVTBuilder builder = new GVTBuilder();
+ root = builder.build(ctx, clonedDoc);
+ } catch (Exception e) {
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ context.getUserAgent().getEventBroadcaster());
+ eventProducer.svgNotBuilt(this, e, image.getInfo().getOriginalURI());
+ return;
+ }
+ // get the 'width' and 'height' attributes of the SVG document
+ float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
+ float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
+
+ float sx = pos.width / w;
+ float sy = pos.height / h;
+
+ ctx = null;
+
+ gen.commentln("%FOPBeginSVG");
+ gen.saveGraphicsState();
+ final boolean clip = false;
+ if (clip) {
+ /*
+ * Clip to the svg area.
+ * Note: To have the svg overlay (under) a text area then use
+ * an fo:block-container
+ */
+ gen.writeln("newpath");
+ gen.defineRect(pos.getMinX() / 1000f, pos.getMinY() / 1000f,
+ pos.width / 1000f, pos.height / 1000f);
+ gen.writeln("clip");
+ }
+
+ // transform so that the coordinates (0,0) is from the top left
+ // and positive is down and to the right. (0,0) is where the
+ // viewBox puts it.
+ gen.concatMatrix(sx, 0, 0, sy, pos.getMinX() / 1000f, pos.getMinY() / 1000f);
+
+ AffineTransform transform = new AffineTransform();
+ // scale to viewbox
+ transform.translate(pos.getMinX(), pos.getMinY());
+ gen.getCurrentState().concatMatrix(transform);
+ try {
+ root.paint(graphics);
+ } catch (Exception e) {
+ SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+ context.getUserAgent().getEventBroadcaster());
+ eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
+ }
+
+ gen.restoreGraphicsState();
+ gen.commentln("%FOPEndSVG");
+ }
+ }
+
+ private InputStream renderSVGToInputStream(RenderingContext context, ImageXMLDOM imageSVG) throws IOException {
+ PNGTranscoder png = new PNGTranscoder();
+ Float width = getDimension(imageSVG.getDocument(), "width") * 8;
+ png.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, width);
+ Float height = getDimension(imageSVG.getDocument(), "height") * 8;
+ png.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, height);
+ TranscoderInput input = new TranscoderInput(imageSVG.getDocument());
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ TranscoderOutput output = new TranscoderOutput(os);
try {
- GVTBuilder builder = new GVTBuilder();
- root = builder.build(ctx, clonedDoc);
- } catch (Exception e) {
+ png.transcode(input, output);
+ } catch (TranscoderException ex) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
- eventProducer.svgNotBuilt(this, e, image.getInfo().getOriginalURI());
- return;
+ eventProducer.svgRenderingError(this, ex, imageSVG.getInfo().getOriginalURI());
+ } finally {
+ os.flush();
+ os.close();
+ }
+ return new ByteArrayInputStream(os.toByteArray());
+ }
+
+ private MaskedImage convertToRGB(BufferedImage alphaImage) {
+ int[] red = new int[256];
+ int[] green = new int[256];
+ int[] blue = new int[256];
+ BufferedImage rgbImage = new BufferedImage(alphaImage.getWidth(),
+ alphaImage.getHeight(), BufferedImage.TYPE_INT_RGB);
+ //Count occurances of each colour in image
+ for (int cx = 0; cx < alphaImage.getWidth(); cx++) {
+ for (int cy = 0; cy < alphaImage.getHeight(); cy++) {
+ int pixelValue = alphaImage.getRGB(cx, cy);
+ Color pixelColor = new Color(pixelValue);
+ red[pixelColor.getRed()]++;
+ green[pixelColor.getGreen()]++;
+ blue[pixelColor.getBlue()]++;
+ }
+ }
+ //Find colour not in image
+ Color alphaSwap = null;
+ for (int i = 0; i < 256; i++) {
+ if (red[i] == 0) {
+ alphaSwap = new Color(i, 0, 0);
+ break;
+ } else if (green[i] == 0) {
+ alphaSwap = new Color(0, i, 0);
+ break;
+ } else if (blue[i] == 0) {
+ alphaSwap = new Color(0, 0, i);
+ break;
+ }
+ }
+ //Check if all variations are used in all three colours
+ if (alphaSwap == null) {
+ //Fallback colour is no unique colour channel can be found
+ alphaSwap = FALLBACK_COLOR;
+ }
+ //Replace alpha channel with the new mask colour
+ for (int cx = 0; cx < alphaImage.getWidth(); cx++) {
+ for (int cy = 0; cy < alphaImage.getHeight(); cy++) {
+ int pixelValue = alphaImage.getRGB(cx, cy);
+ if (pixelValue == 0) {
+ rgbImage.setRGB(cx, cy, alphaSwap.getRGB());
+ } else {
+ rgbImage.setRGB(cx, cy, alphaImage.getRGB(cx, cy));
+ }
+ }
+ }
+ return new MaskedImage(rgbImage, alphaSwap);
+ }
+
+ private static class MaskedImage {
+ private Color maskColor = new Color(0, 0, 0);
+ private BufferedImage image;
+
+ public MaskedImage(BufferedImage image, Color maskColor) {
+ this.image = image;
+ this.maskColor = maskColor;
+ }
+
+ public Color getMaskColor() {
+ return maskColor;
+ }
+
+ public BufferedImage getImage() {
+ return image;
+ }
+ }
+
+ private Float getDimension(Document document, String dimension) {
+ if (document.getFirstChild().getAttributes().getNamedItem(dimension) != null) {
+ String width = document.getFirstChild().getAttributes().getNamedItem(dimension).getNodeValue();
+ width = width.replaceAll("[^\\d.]", "");
+ return Float.parseFloat(width);
}
- // get the 'width' and 'height' attributes of the SVG document
- float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
- float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
-
- float sx = pos.width / w;
- float sy = pos.height / h;
-
- ctx = null;
-
- gen.commentln("%FOPBeginSVG");
- gen.saveGraphicsState();
- final boolean clip = false;
- if (clip) {
- /*
- * Clip to the svg area.
- * Note: To have the svg overlay (under) a text area then use
- * an fo:block-container
- */
- gen.writeln("newpath");
- gen.defineRect(pos.getMinX() / 1000f, pos.getMinY() / 1000f,
- pos.width / 1000f, pos.height / 1000f);
- gen.writeln("clip");
- }
-
- // transform so that the coordinates (0,0) is from the top left
- // and positive is down and to the right. (0,0) is where the
- // viewBox puts it.
- gen.concatMatrix(sx, 0, 0, sy, pos.getMinX() / 1000f, pos.getMinY() / 1000f);
-
- AffineTransform transform = new AffineTransform();
- // scale to viewbox
- transform.translate(pos.getMinX(), pos.getMinY());
- gen.getCurrentState().concatMatrix(transform);
+ return null;
+ }
+
+ private boolean shouldRaster(ImageXMLDOM image) {
+ //A list of objects on which to check opacity
try {
- root.paint(graphics);
- } catch (Exception e) {
- SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
- context.getUserAgent().getEventBroadcaster());
- eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
+ List<String> gradMatches = new ArrayList<String>();
+ gradMatches.add("radialGradient");
+ gradMatches.add("linearGradient");
+ return recurseSVGElements(image.getDocument().getChildNodes(), gradMatches, false);
+ } finally {
+ gradientsFound.clear();
}
+ }
- gen.restoreGraphicsState();
- gen.commentln("%FOPEndSVG");
+ private boolean recurseSVGElements(NodeList childNodes, List<String> gradMatches, boolean isMatched) {
+ boolean opacityFound = false;
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node curNode = childNodes.item(i);
+ if (isMatched && curNode.getLocalName() != null && curNode.getLocalName().equals("stop")) {
+ if (curNode.getAttributes().getNamedItem("style") != null) {
+ String[] stylePairs = curNode.getAttributes().getNamedItem("style").getNodeValue()
+ .split(";");
+ for (int styleAtt = 0; styleAtt < stylePairs.length; styleAtt++) {
+ String[] style = stylePairs[styleAtt].split(":");
+ if (style[0].equalsIgnoreCase("stop-opacity")) {
+ if (Double.parseDouble(style[1]) < 1) {
+ return true;
+ }
+ }
+ }
+ }
+ if (curNode.getAttributes().getNamedItem("stop-opacity") != null) {
+ String opacityValue = curNode.getAttributes().getNamedItem("stop-opacity").getNodeValue();
+ if (Double.parseDouble(opacityValue) < 1) {
+ return true;
+ }
+ }
+ }
+ String nodeName = curNode.getLocalName();
+ //Special case where rasterization needed for radial gradients
+ if (nodeName != null && nodeName.equals("ellipse")) {
+ String found = "";
+ String ellipseFill = curNode.getAttributes().getNamedItem("fill").getNodeValue();
+ Pattern pattern = Pattern.compile("#(.*?)\\)");
+ Matcher matcher = pattern.matcher(ellipseFill);
+ if (matcher.find()) {
+ found = matcher.group(1);
+ }
+ if (gradientsFound.get(found) != null) {
+ return true;
+ }
+ }
+ boolean inMatch = false;
+ if (!isMatched) {
+ inMatch = nodeName != null && gradMatches.contains(nodeName);
+ if (inMatch) {
+ gradientsFound.put(curNode.getAttributes().getNamedItem("id").getNodeValue(), nodeName);
+ }
+ } else {
+ inMatch = true;
+ }
+ opacityFound = recurseSVGElements(curNode.getChildNodes(), gradMatches, inMatch);
+ if (opacityFound) {
+ return true;
+ }
+ }
+ return opacityFound;
}
/** {@inheritDoc} */
Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java?rev=1541551&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java Wed Nov 13 15:24:26 2013
@@ -0,0 +1,143 @@
+/*
+ * 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.ps.svg;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.shading.FunctionDelegate;
+import org.apache.fop.render.shading.FunctionPattern;
+
+public class PSFunction implements Function {
+
+ private FunctionDelegate delegate;
+
+ /**
+ * Creates a Postscript function dictionary
+ * @param theFunctionType The function type (0 = Sampled, 2 = Exponential
+ * Interpolation, 3 = Stitching)
+ * @param theDomain The function domain
+ * @param theRange Range used for clipping
+ * @param theFunctions An array of sub-functions such as determining the
+ * colour values used in a gradient.
+ * @param theBounds Bounds determines where each boundary exists for whatever
+ * the function is mean't. In a gradient case, it would be the point between
+ * colours.
+ * @param theEncode The function encoding
+ */
+ public PSFunction(int theFunctionType, List<Double> theDomain,
+ List<Double> theRange, List<Function> theFunctions,
+ List<Double> theBounds, List<Double> theEncode) {
+ delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange, theFunctions,
+ theBounds, theEncode);
+ }
+
+ /**
+ * Creates a Postscript function dictionary
+ * @param theFunctionType The function type (0 = Sampled, 2 = Exponential
+ * Interpolation, 3 = Stitching)
+ * @param theDomain The function domain
+ * @param theRange Range used for clipping
+ * @param theCZero In a gradient, this would be the first colour
+ * @param theCOne In a gradient, this would be the second colour
+ * @param theInterpolationExponentN Determines the number of values
+ * the function returns.
+ */
+ public PSFunction(int theFunctionType, List<Double> theDomain,
+ List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
+ double theInterpolationExponentN) {
+ delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange, theCZero,
+ theCOne, theInterpolationExponentN);
+ }
+
+ /**
+ * Outputs the function to a byte array
+ */
+ public byte[] toByteString() {
+ FunctionPattern pattern = new FunctionPattern(this);
+ try {
+ return pattern.toWriteableString().getBytes("UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ //This should have been made an enum type to avoid throwing exceptions.
+ return new byte[0];
+ }
+ }
+
+ public int getFunctionType() {
+ return delegate.getFunctionType();
+ }
+
+ public List<Double> getBounds() {
+ return delegate.getBounds();
+ }
+
+ public List<Double> getDomain() {
+ return delegate.getDomain();
+ }
+
+ public List<Double> getSize() {
+ return delegate.getSize();
+ }
+
+ public List<String> getFilter() {
+ return delegate.getFilter();
+ }
+
+ public List<Double> getEncode() {
+ return delegate.getEncode();
+ }
+
+ public List<Function> getFunctions() {
+ return delegate.getFunctions();
+ }
+
+ public int getBitsPerSample() {
+ return delegate.getBitsPerSample();
+ }
+
+ public double getInterpolationExponentN() {
+ return delegate.getInterpolationExponentN();
+ }
+
+ public int getOrder() {
+ return delegate.getOrder();
+ }
+
+ public List<Double> getRange() {
+ return delegate.getRange();
+ }
+
+ public List<Double> getDecode() {
+ return delegate.getDecode();
+ }
+
+ public StringBuffer getDataStream() {
+ return delegate.getDataStream();
+ }
+
+ public List<Double> getCZero() {
+ return delegate.getCZero();
+ }
+
+ public List<Double> getCOne() {
+ return delegate.getCOne();
+ }
+}
Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java?rev=1541551&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java Wed Nov 13 15:24:26 2013
@@ -0,0 +1,103 @@
+/*
+ * 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.ps.svg;
+
+import java.util.List;
+
+import org.apache.fop.render.shading.Pattern;
+import org.apache.fop.render.shading.Shading;
+
+public class PSPattern implements Pattern {
+
+ /**
+ * Either one (1) for tiling, or two (2) for shading.
+ */
+ protected int patternType = 2; // Default
+
+ /**
+ * The Shading object comprising the Type 2 pattern
+ */
+ protected PSShading shading = null;
+
+ /**
+ * List of Integers represetning the Extended unique Identifier
+ */
+ protected List xUID = null;
+
+ /**
+ * TODO use PDFGState
+ * String representing the extended Graphics state.
+ * Probably will never be used like this.
+ */
+ protected StringBuffer extGState = null;
+
+ /**
+ * Creates a radial or axial shading pattern
+ * @param thePatternType The pattern type which will be 3 for radial and 2 for axial
+ * @param theShading The shading object to determine how the gradient
+ * is drawn
+ * @param theXUID The XUID
+ * @param theExtGState The exit state
+ */
+ public PSPattern(int thePatternType, Shading theShading, List theXUID,
+ StringBuffer theExtGState) {
+ this.patternType = 2; // thePatternType;
+ assert theShading instanceof PSShading;
+ this.shading = (PSShading)theShading;
+ this.xUID = theXUID;
+ this.extGState = theExtGState; // always null
+ }
+
+ /**
+ * Outputs the radial or axial pattern as a string dictionary to insert
+ * into a postscript document.
+ */
+ public String toString() {
+ int vectorSize = 0;
+ int tempInt = 0;
+ StringBuffer p = new StringBuffer(64);
+ p.append("/Pattern setcolorspace\n");
+ p.append("<< \n/Type /Pattern \n");
+
+ p.append("/PatternType " + this.patternType + " \n");
+
+ if (this.shading != null) {
+ p.append("/Shading " + this.shading.toString() + " \n");
+ }
+
+ if (this.xUID != null) {
+ vectorSize = this.xUID.size();
+ p.append("/XUID [ ");
+ for (tempInt = 0; tempInt < vectorSize; tempInt++) {
+ p.append((this.xUID.get(tempInt)) + " ");
+ }
+ p.append("] \n");
+ }
+
+ if (this.extGState != null) {
+ p.append("/ExtGState " + this.extGState + " \n");
+ }
+
+ p.append(">> \n");
+ p.append("matrix makepattern setcolor\n");
+
+ return p.toString();
+ }
+}
Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org