You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2014/02/02 16:20:53 UTC
svn commit: r1563633 - in
/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics:
pattern/PDShadingPatternResources.java shading/AxialShadingContext.java
shading/PDShadingType2.java shading/RadialShadingContext.java
Author: lehmi
Date: Sun Feb 2 15:20:53 2014
New Revision: 1563633
URL: http://svn.apache.org/r1563633
Log:
PDFBOX-615: take the shading matrix into account based on a proposal by Luis Bernado, add background support
Modified:
pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java
pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/AxialShadingContext.java
pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShadingType2.java
pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java
Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java?rev=1563633&r1=1563632&r2=1563633&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/PDShadingPatternResources.java Sun Feb 2 15:20:53 2014
@@ -211,10 +211,10 @@ public class PDShadingPatternResources e
paint = new Type1ShadingPaint((PDShadingType1)getShading(), getMatrix(), pageHeight);
break;
case PDShadingResources.SHADING_TYPE2:
- paint = new AxialShadingPaint((PDShadingType2)getShading(), null, pageHeight);
+ paint = new AxialShadingPaint((PDShadingType2)getShading(), getMatrix(), pageHeight);
break;
case PDShadingResources.SHADING_TYPE3:
- paint = new RadialShadingPaint((PDShadingType3)getShading(), null, pageHeight);
+ paint = new RadialShadingPaint((PDShadingType3)getShading(), getMatrix(), pageHeight);
break;
case PDShadingResources.SHADING_TYPE4:
case PDShadingResources.SHADING_TYPE5:
Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/AxialShadingContext.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/AxialShadingContext.java?rev=1563633&r1=1563632&r2=1563633&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/AxialShadingContext.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/AxialShadingContext.java Sun Feb 2 15:20:53 2014
@@ -17,9 +17,12 @@
package org.apache.pdfbox.pdmodel.graphics.shading;
import java.awt.PaintContext;
+import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.IOException;
@@ -44,15 +47,14 @@ import org.apache.pdfbox.util.Matrix;
public class AxialShadingContext implements PaintContext
{
- private ColorModel colorModel;
- private PDFunction function;
+ private ColorModel outputColorModel;
private ColorSpace shadingColorSpace;
private PDFunction shadingTinttransform;
+ private PDShadingType2 shadingType;
private float[] coords;
private float[] domain;
- private int[] extend0Values;
- private int[] extend1Values;
+ private float[] background;
private boolean[] extend;
private double x1x0;
private double y1y0;
@@ -77,6 +79,7 @@ public class AxialShadingContext impleme
public AxialShadingContext(PDShadingType2 shadingType2, ColorModel colorModelValue,
AffineTransform xform, Matrix ctm, int pageHeight)
{
+ shadingType = shadingType2;
coords = shadingType2.getCoords().toFloatArray();
if (ctm != null)
{
@@ -99,94 +102,78 @@ public class AxialShadingContext impleme
coords[1] = pageHeight + translateY - coords[1];
coords[3] = pageHeight + translateY - coords[3];
}
- // colorSpace
- try
+ // get the shading colorSpace
+ try
{
- PDColorSpace cs = shadingType2.getColorSpace();
+ PDColorSpace cs = shadingType.getColorSpace();
if (!(cs instanceof PDDeviceRGB))
{
// we have to create an instance of the shading colorspace if it isn't RGB
shadingColorSpace = cs.getJavaColorSpace();
+ // get the tint transformation function if the colorspace has one
if (cs instanceof PDDeviceN)
{
- shadingTinttransform = ((PDDeviceN)cs).getTintTransform();
+ shadingTinttransform = ((PDDeviceN) cs).getTintTransform();
}
else if (cs instanceof PDSeparation)
{
- shadingTinttransform = ((PDSeparation)cs).getTintTransform();
+ shadingTinttransform = ((PDSeparation) cs).getTintTransform();
}
}
- }
- catch (IOException exception)
- {
- LOG.error("error while creating colorSpace", exception);
- }
- // colorModel
- if (colorModelValue != null)
- {
- colorModel = colorModelValue;
- }
- else
- {
- try
- {
- // TODO bpc != 8 ??
- colorModel = shadingType2.getColorSpace().createColorModel(8);
- }
- catch(IOException exception)
- {
- LOG.error("error while creating colorModel", exception);
- }
- }
- // shading function
- try
- {
- function = shadingType2.getFunction();
}
- catch(IOException exception)
+ catch (IOException exception)
{
- LOG.error("error while creating a function", exception);
+ LOG.error("error while creating colorSpace", exception);
}
+ // create the output colormodel using RGB+alpha as colorspace
+ ColorSpace outputCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ outputColorModel = new ComponentColorModel(outputCS, true, false, Transparency.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
// domain values
- if (shadingType2.getDomain() != null)
+ if (shadingType.getDomain() != null)
{
- domain = shadingType2.getDomain().toFloatArray();
+ domain = shadingType.getDomain().toFloatArray();
}
- else
+ else
{
// set default values
- domain = new float[]{0,1};
+ domain = new float[] { 0, 1 };
}
// extend values
- COSArray extendValues = shadingType2.getExtend();
- if (shadingType2.getExtend() != null)
+ COSArray extendValues = shadingType.getExtend();
+ if (shadingType.getExtend() != null)
{
extend = new boolean[2];
- extend[0] = ((COSBoolean)extendValues.get(0)).getValue();
- extend[1] = ((COSBoolean)extendValues.get(1)).getValue();
+ extend[0] = ((COSBoolean) extendValues.get(0)).getValue();
+ extend[1] = ((COSBoolean) extendValues.get(1)).getValue();
}
else
{
// set default values
- extend = new boolean[]{false,false};
+ extend = new boolean[] { false, false };
}
// calculate some constants to be used in getRaster
- x1x0 = coords[2] - coords[0];
+ x1x0 = coords[2] - coords[0];
y1y0 = coords[3] - coords[1];
- d1d0 = domain[1]-domain[0];
- denom = Math.pow(x1x0,2) + Math.pow(y1y0, 2);
- // TODO take a possible Background value into account
-
+ d1d0 = domain[1] - domain[0];
+ denom = Math.pow(x1x0, 2) + Math.pow(y1y0, 2);
+
+ // get background values if available
+ COSArray bg = shadingType2.getBackground();
+ if (bg != null)
+ {
+ background = bg.toFloatArray();
+ }
}
/**
* {@inheritDoc}
*/
public void dispose()
{
- colorModel = null;
- function = null;
+ outputColorModel = null;
shadingColorSpace = null;
shadingTinttransform = null;
+ shadingType = null;
}
/**
@@ -194,7 +181,7 @@ public class AxialShadingContext impleme
*/
public ColorModel getColorModel()
{
- return colorModel;
+ return outputColorModel;
}
/**
@@ -204,40 +191,50 @@ public class AxialShadingContext impleme
{
// create writable raster
WritableRaster raster = getColorModel().createCompatibleWritableRaster(w, h);
- float[] input = new float[1];
- int[] data = new int[w * h * 3];
- boolean saveExtend0 = false;
- boolean saveExtend1 = false;
- for (int j = 0; j < h; j++)
+ boolean useBackground = false;
+ int[] data = new int[w * h * 4];
+ for (int j = 0; j < h; j++)
{
- for (int i = 0; i < w; i++)
+ for (int i = 0; i < w; i++)
{
- int index = (j * w + i) * 3;
- double inputValue = x1x0 * (x + i - coords[0]);
+ useBackground = false;
+ double inputValue = x1x0 * (x + i - coords[0]);
inputValue += y1y0 * (y + j - coords[1]);
- inputValue /= denom;
+ // TODO this happens if start == end, see PDFBOX-1442
+ if (denom == 0)
+ {
+ if (background != null)
+ {
+ useBackground = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ inputValue /= denom;
+ }
// input value is out of range
if (inputValue < domain[0])
{
// the shading has to be extended if extend[0] == true
if (extend[0])
{
- if (extend0Values == null)
+ inputValue = domain[0];
+ }
+ else
+ {
+ if (background != null)
{
- inputValue = domain[0];
- saveExtend0 = true;
+ useBackground = true;
}
else
{
- // use the chached values
- System.arraycopy(extend0Values, 0, data, index, 3);
continue;
}
}
- else
- {
- continue;
- }
}
// input value is out of range
else if (inputValue > domain[1])
@@ -245,61 +242,103 @@ public class AxialShadingContext impleme
// the shading has to be extended if extend[1] == true
if (extend[1])
{
- if (extend1Values == null)
+ inputValue = domain[1];
+ }
+ else
+ {
+ if (background != null)
{
- inputValue = domain[1];
- saveExtend1 = true;
+ useBackground = true;
}
else
{
- // use the chached values
- System.arraycopy(extend1Values, 0, data, index, 3);
continue;
}
}
- else
+ }
+ float[] values = null;
+ int index = (j * w + i) * 4;
+ if (useBackground)
+ {
+ // use the given backgound color values
+ values = background;
+ }
+ else
+ {
+ try
{
- continue;
+ float input = (float) (domain[0] + (d1d0 * inputValue));
+ values = shadingType.evalFunction(input);
+ }
+ catch (IOException exception)
+ {
+ LOG.error("error while processing a function", exception);
}
}
- input[0] = (float)(domain[0] + (d1d0*inputValue));
- float[] values = null;
- try
+ // convert color values from shading colorspace to RGB if necessary
+ if (shadingColorSpace != null)
{
- values = function.eval(input);
- // convert color values from shading colorspace to RGB
- if (shadingColorSpace != null)
+ if (shadingTinttransform != null)
{
- if (shadingTinttransform != null)
+ try
{
values = shadingTinttransform.eval(values);
}
- values = shadingColorSpace.toRGB(values);
+ catch (IOException exception)
+ {
+ LOG.error("error while processing a function", exception);
+ }
}
- }
- catch (IOException exception)
- {
- LOG.error("error while processing a function", exception);
- }
- data[index] = (int)(values[0]*255);
- data[index+1] = (int)(values[1]*255);
- data[index+2] = (int)(values[2]*255);
- if (saveExtend0)
- {
- // chache values
- extend0Values = new int[3];
- System.arraycopy(data, index, extend0Values, 0, 3);
- }
- if (saveExtend1)
- {
- // chache values
- extend1Values = new int[3];
- System.arraycopy(data, index, extend1Values, 0, 3);
+ values = shadingColorSpace.toRGB(values);
}
+ data[index] = (int) (values[0] * 255);
+ data[index + 1] = (int) (values[1] * 255);
+ data[index + 2] = (int) (values[2] * 255);
+ data[index + 3] = 255;
}
}
raster.setPixels(0, 0, w, h, data);
return raster;
}
+ /**
+ * Returns the coords values.
+ *
+ * @return the coords values as array
+ */
+ public float[] getCoords()
+ {
+ return coords;
+ }
+
+ /**
+ * Returns the domain values.
+ *
+ * @return the domain values as array
+ */
+ public float[] getDomain()
+ {
+ return domain;
+ }
+
+ /**
+ * Returns the extend values.
+ *
+ * @return the extend values as array
+ */
+ public boolean[] getExtend()
+ {
+ return extend;
+ }
+
+ /**
+ * Returns the function used for the shading tint transformation.
+ *
+ * @return the shading tint transformation function
+ */
+ public PDFunction getShadingTintTransform()
+ {
+ return shadingTinttransform;
+ }
+
}
Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShadingType2.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShadingType2.java?rev=1563633&r1=1563632&r2=1563633&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShadingType2.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/PDShadingType2.java Sun Feb 2 15:20:53 2014
@@ -21,6 +21,7 @@ package org.apache.pdfbox.pdmodel.graphi
import java.io.IOException;
import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.common.function.PDFunction;
@@ -37,6 +38,8 @@ public class PDShadingType2 extends PDSh
private COSArray domain = null;
private COSArray extend = null;
private PDFunction function = null;
+ private PDFunction[] functionArray = null;
+
/**
* Constructor using the given shading dictionary.
@@ -177,6 +180,8 @@ public class PDShadingType2 extends PDSh
*
* @exception IOException If we are unable to create the PDFunction object.
*
+ * @deprecated
+ *
*/
public PDFunction getFunction() throws IOException
{
@@ -187,4 +192,63 @@ public class PDShadingType2 extends PDSh
return function;
}
+ /**
+ * Provide the function(s) of the shading dictionary as array.
+ *
+ * @return an array containing the function(s)
+ * @throws IOException throw if something went wrong
+ */
+ private PDFunction[] getFunctionsArray() throws IOException
+ {
+ if (functionArray == null)
+ {
+ COSBase functionObject = getCOSDictionary().getDictionaryObject(COSName.FUNCTION);
+ if (functionObject instanceof COSDictionary)
+ {
+ functionArray = new PDFunction[1];
+ functionArray[0] = PDFunction.create(functionObject);
+ }
+ else
+ {
+ COSArray functionCOSArray = (COSArray)functionObject;
+ int numberOfFunctions = functionCOSArray.size();
+ functionArray = new PDFunction[numberOfFunctions];
+ for (int i=0; i<numberOfFunctions; i++)
+ {
+ functionArray[i] = PDFunction.create(functionCOSArray.get(i));
+ }
+ }
+ }
+ return functionArray;
+ }
+
+ /**
+ * Convert the input value using the functions of the shading dictionary.
+ *
+ * @param inputValue the input value
+ * @return the output values
+ * @throws IOException thrown if something went wrong
+ */
+ public float[] evalFunction(float inputValue) throws IOException
+ {
+ float[] input = new float[] {inputValue};
+ PDFunction[] functions = getFunctionsArray();
+ int numberOfFunctions = functions.length;
+ float[] returnValues = null;
+ if (numberOfFunctions == 1)
+ {
+ returnValues = functions[0].eval(input);
+ }
+ else
+ {
+ returnValues = new float[numberOfFunctions];
+ for (int i=0; i<numberOfFunctions;i++)
+ {
+ float[] newValue = functions[i].eval(input);
+ returnValues[i] = newValue[0];
+ }
+ }
+ return returnValues;
+ }
+
}
Modified: pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java?rev=1563633&r1=1563632&r2=1563633&view=diff
==============================================================================
--- pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java (original)
+++ pdfbox/branches/1.8/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/RadialShadingContext.java Sun Feb 2 15:20:53 2014
@@ -17,9 +17,12 @@
package org.apache.pdfbox.pdmodel.graphics.shading;
import java.awt.PaintContext;
+import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.IOException;
@@ -44,16 +47,16 @@ import org.apache.pdfbox.util.Matrix;
public class RadialShadingContext implements PaintContext
{
- private ColorModel colorModel;
+ private ColorModel outputColorModel;
private PDFunction function;
private ColorSpace shadingColorSpace;
private PDFunction shadingTinttransform;
+ private PDShadingType3 shadingType;
private float[] coords;
private float[] domain;
- private int[] extend0Values;
- private int[] extend1Values;
private boolean[] extend;
+ private float[] background;
private double x1x0;
private double y1y0;
private double r1r0;
@@ -82,6 +85,7 @@ public class RadialShadingContext implem
public RadialShadingContext(PDShadingType3 shadingType3, ColorModel colorModelValue,
AffineTransform xform, Matrix ctm, int pageHeight)
{
+ shadingType = shadingType3;
coords = shadingType3.getCoords().toFloatArray();
if (ctm != null)
{
@@ -90,12 +94,18 @@ public class RadialShadingContext implem
// transform the coords from shading to user space
ctm.createAffineTransform().transform(coords, 0, coordsTemp, 0, 1);
ctm.createAffineTransform().transform(coords, 3, coordsTemp, 3, 1);
+ // scale radius to user space
+ coords[2] *= ctm.getXScale();
+ coords[5] *= ctm.getXScale();
// move the 0,0-reference
coordsTemp[1] = pageHeight - coordsTemp[1];
coordsTemp[4] = pageHeight - coordsTemp[4];
// transform the coords from user to device space
xform.transform(coordsTemp, 0, coords, 0, 1);
xform.transform(coordsTemp, 3, coords, 3, 1);
+ // scale radius to device space
+ coords[2] *= xform.getScaleX();
+ coords[5] *= xform.getScaleX();
}
else
{
@@ -106,98 +116,82 @@ public class RadialShadingContext implem
coords[1] = pageHeight + translateY - coords[1];
coords[4] = pageHeight + translateY - coords[4];
}
- // colorSpace
- try
+ // get the shading colorSpace
+ try
{
- PDColorSpace cs = shadingType3.getColorSpace();
+ PDColorSpace cs = shadingType.getColorSpace();
if (!(cs instanceof PDDeviceRGB))
{
// we have to create an instance of the shading colorspace if it isn't RGB
shadingColorSpace = cs.getJavaColorSpace();
if (cs instanceof PDDeviceN)
{
- shadingTinttransform = ((PDDeviceN)cs).getTintTransform();
+ shadingTinttransform = ((PDDeviceN) cs).getTintTransform();
}
else if (cs instanceof PDSeparation)
{
- shadingTinttransform = ((PDSeparation)cs).getTintTransform();
+ shadingTinttransform = ((PDSeparation) cs).getTintTransform();
}
}
- }
- catch (IOException exception)
- {
- LOG.error("error while creating colorSpace", exception);
}
- // colorModel
- if (colorModelValue != null)
- {
- colorModel = colorModelValue;
- }
- else
+ catch (IOException exception)
{
- try
- {
- // TODO bpc != 8 ??
- colorModel = shadingType3.getColorSpace().createColorModel(8);
- }
- catch(IOException exception)
- {
- LOG.error("error while creating colorModel", exception);
- }
- }
- // shading function
- try
- {
- function = shadingType3.getFunction();
- }
- catch(IOException exception)
- {
- LOG.error("error while creating a function", exception);
+ LOG.error("error while creating colorSpace", exception);
}
+ // create the output colormodel using RGB+alpha as colorspace
+ ColorSpace outputCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ outputColorModel = new ComponentColorModel(outputCS, true, false, Transparency.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
// domain values
- if (shadingType3.getDomain() != null)
+ if (shadingType.getDomain() != null)
{
- domain = shadingType3.getDomain().toFloatArray();
+ domain = shadingType.getDomain().toFloatArray();
}
- else
+ else
{
// set default values
- domain = new float[]{0,1};
+ domain = new float[] { 0, 1 };
}
// extend values
- COSArray extendValues = shadingType3.getExtend();
- if (shadingType3.getExtend() != null)
+ COSArray extendValues = shadingType.getExtend();
+ if (shadingType.getExtend() != null)
{
extend = new boolean[2];
- extend[0] = ((COSBoolean)extendValues.get(0)).getValue();
- extend[1] = ((COSBoolean)extendValues.get(1)).getValue();
+ extend[0] = ((COSBoolean) extendValues.get(0)).getValue();
+ extend[1] = ((COSBoolean) extendValues.get(1)).getValue();
}
else
{
// set default values
- extend = new boolean[]{false,false};
+ extend = new boolean[] { false, false };
}
// calculate some constants to be used in getRaster
- x1x0 = coords[3] - coords[0];
+ x1x0 = coords[3] - coords[0];
y1y0 = coords[4] - coords[1];
r1r0 = coords[5] - coords[2];
- x1x0pow2 = Math.pow(x1x0,2);
- y1y0pow2 = Math.pow(y1y0,2);
- r0pow2 = Math.pow(coords[2],2);
+ x1x0pow2 = Math.pow(x1x0, 2);
+ y1y0pow2 = Math.pow(y1y0, 2);
+ r0pow2 = Math.pow(coords[2], 2);
denom = x1x0pow2 + y1y0pow2 - Math.pow(r1r0, 2);
- d1d0 = domain[1]-domain[0];
- // TODO take a possible Background value into account
-
+ d1d0 = domain[1] - domain[0];
+
+ // get background values if available
+ COSArray bg = shadingType3.getBackground();
+ if (bg != null)
+ {
+ background = bg.toFloatArray();
+ }
}
/**
* {@inheritDoc}
*/
public void dispose()
{
- colorModel = null;
+ outputColorModel = null;
function = null;
shadingColorSpace = null;
shadingTinttransform = null;
+ shadingType = null;
}
/**
@@ -205,7 +199,7 @@ public class RadialShadingContext implem
*/
public ColorModel getColorModel()
{
- return colorModel;
+ return outputColorModel;
}
/**
@@ -215,125 +209,146 @@ public class RadialShadingContext implem
{
// create writable raster
WritableRaster raster = getColorModel().createCompatibleWritableRaster(w, h);
- float[] input = new float[1];
- float inputValue;
- boolean saveExtend0 = false;
- boolean saveExtend1 = false;
- int[] data = new int[w * h * 3];
- for (int j = 0; j < h; j++)
+ float inputValue = -1;
+ boolean useBackground;
+ int[] data = new int[w * h * 4];
+ for (int j = 0; j < h; j++)
{
- for (int i = 0; i < w; i++)
+ for (int i = 0; i < w; i++)
{
- int index = (j * w + i) * 3;
+ useBackground = false;
float[] inputValues = calculateInputValues(x + i, y + j);
- // choose 1 of the 2 values
- if (inputValues[0] >= domain[0] && inputValues[0] <= domain[1])
+ if (Float.isNaN(inputValues[0]) && Float.isNaN(inputValues[1]))
{
- // both values are in the domain -> choose the larger one
- if(inputValues[1] >= domain[0] && inputValues[1] <= domain[1])
+ if (background != null)
{
- inputValue = Math.max(inputValues[0], inputValues[1]);
- }
- // first value is in the domain, the second not -> choose first value
+ useBackground = true;
+ }
else
{
- inputValue = inputValues[0];
+ continue;
}
}
else
{
- // first value is not in the domain, but the second -> choose second value
- if(inputValues[1] >= domain[0] && inputValues[1] <= domain[1])
+ // choose 1 of the 2 values
+ if (inputValues[0] >= domain[0] && inputValues[0] <= domain[1])
{
- inputValue = inputValues[1];
+ // both values are in the domain -> choose the larger one
+ if (inputValues[1] >= domain[0] && inputValues[1] <= domain[1])
+ {
+ inputValue = Math.max(inputValues[0], inputValues[1]);
+ }
+ // first value is in the domain, the second not -> choose first value
+ else
+ {
+ inputValue = inputValues[0];
+ }
}
- // TODO
- // both are not in the domain -> choose the first as I don't know it better
else
{
- inputValue = inputValues[0];
- }
- }
- // input value is out of range
- if (inputValue < domain[0])
- {
- // the shading has to be extended if extend[0] == true
- if (extend[0])
- {
- if (extend0Values == null)
+ // first value is not in the domain, but the second -> choose second value
+ if (inputValues[1] >= domain[0] && inputValues[1] <= domain[1])
{
- inputValue = domain[0];
- saveExtend0 = true;
+ inputValue = inputValues[1];
}
+ // both are not in the domain (is this correct, or is there some miscalculation??)
else
{
- // use the chached values
- System.arraycopy(extend0Values, 0, data, index, 3);
- continue;
+ // TODO don't know what to do in such cases. The following works
+ // with the given examples
+ // choose the smaller if extend[0] is set to true
+ if (extend[0])
+ {
+ inputValue = Math.min(inputValues[0], inputValues[1]);
+ }
+ // choose the bigger one in all other cases
+ else
+ {
+ inputValue = Math.max(inputValues[0], inputValues[1]);
+ }
}
}
- else
+ // input value is out of range
+ if (inputValue > domain[1])
{
- continue;
- }
- }
- // input value is out of range
- else if (inputValue > domain[1])
- {
- // the shading has to be extended if extend[1] == true
- if (extend[1])
- {
- if (extend1Values == null)
+ // the shading has to be extended if extend[1] == true
+ if (extend[1])
{
inputValue = domain[1];
- saveExtend1 = true;
}
else
{
- // use the chached values
- System.arraycopy(extend1Values, 0, data, index, 3);
- continue;
+ if (background != null)
+ {
+ useBackground = true;
+ }
+ else
+ {
+ continue;
+ }
}
}
- else
+ // input value is out of range
+ else if (inputValue < domain[0])
{
- continue;
- }
- }
- input[0] = (float)(domain[0] + (d1d0*inputValue));
- float[] values = null;
- try
- {
- values = function.eval(input);
- // convert color values from shading colorspace to RGB
- if (shadingColorSpace != null)
- {
- if (shadingTinttransform != null)
+ // the shading has to be extended if extend[0] == true
+ if (extend[0])
{
- values = shadingTinttransform.eval(values);
+ inputValue = domain[0];
+ }
+ else
+ {
+ if (background != null)
+ {
+ useBackground = true;
+ }
+ else
+ {
+ continue;
+ }
}
- values = shadingColorSpace.toRGB(values);
}
}
- catch (IOException exception)
+ float[] values = null;
+ int index = (j * w + i) * 4;
+ if (useBackground)
{
- LOG.error("error while processing a function", exception);
+ // use the given backgound color values
+ values = background;
}
- data[index] = (int)(values[0]*255);
- data[index+1] = (int)(values[1]*255);
- data[index+2] = (int)(values[2]*255);
- if (saveExtend0)
+ else
{
- // chache values
- extend0Values = new int[3];
- System.arraycopy(data, index, extend0Values, 0, 3);
+ try
+ {
+ float input = (float) (domain[0] + (d1d0 * inputValue));
+ values = shadingType.evalFunction(input);
+ }
+ catch (IOException exception)
+ {
+ LOG.error("error while processing a function", exception);
+ }
}
- if (saveExtend1)
+ // convert color values from shading colorspace to RGB
+ if (shadingColorSpace != null)
{
- // chache values
- extend1Values = new int[3];
- System.arraycopy(data, index, extend1Values, 0, 3);
+ if (shadingTinttransform != null)
+ {
+ try
+ {
+ values = shadingTinttransform.eval(values);
+ }
+ catch (IOException exception)
+ {
+ LOG.error("error while processing a function", exception);
+ }
+ }
+ values = shadingColorSpace.toRGB(values);
}
+ data[index] = (int) (values[0] * 255);
+ data[index + 1] = (int) (values[1] * 255);
+ data[index + 2] = (int) (values[2] * 255);
+ data[index + 3] = 255;
}
}
raster.setPixels(0, 0, w, h, data);
@@ -365,13 +380,59 @@ public class RadialShadingContext implem
*
* The following code calculates the 2 possible values of s
*/
+ double p = -(x - coords[0]) * x1x0 - (y - coords[1]) * y1y0 - coords[2] * r1r0;
+ double q = (Math.pow(x - coords[0], 2) + Math.pow(y - coords[1], 2) - r0pow2);
+ double root = Math.sqrt(p * p - denom * q);
+ float root1 = (float) ((-p + root) / denom);
+ float root2 = (float) ((-p - root) / denom);
+ if (denom < 0)
+ {
+ return new float[] { root1, root2 };
+ }
+ else
+ {
+ return new float[] { root2, root1 };
+ }
+ }
+
+ /**
+ * Returns the coords values.
+ *
+ * @return the coords values as array
+ */
+ public float[] getCoords()
+ {
+ return coords;
+ }
+
+ /**
+ * Returns the domain values.
+ *
+ * @return the domain values as array
+ */
+ public float[] getDomain()
+ {
+ return domain;
+ }
- float[] values = new float[2];
- double p = (-0.25)*((x - coords[0])*x1x0 + (y - coords[1])*y1y0 - r1r0) / denom;
- double q = (Math.pow(x - coords[0],2) + Math.pow(y - coords[1],2) - r0pow2) / denom;
- double root = Math.sqrt(Math.pow(p , 2) - q);
- values[0] = (float)((-1)*p + root);
- values[1] = (float)((-1)*p - root);
- return values;
+ /**
+ * Returns the extend values.
+ *
+ * @return the extend values as array
+ */
+ public boolean[] getExtend()
+ {
+ return extend;
}
+
+ /**
+ * Returns the function used for the shading tint transformation.
+ *
+ * @return the shading tint transformation function
+ */
+ public PDFunction getShadingTintTransform()
+ {
+ return shadingTinttransform;
+ }
+
}