PatchMeshesShadingContext.java (pdfbox-2.0.23-src) | : | PatchMeshesShadingContext.java (pdfbox-2.0.24-src) | ||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
package org.apache.pdfbox.pdmodel.graphics.shading; | package org.apache.pdfbox.pdmodel.graphics.shading; | |||
import java.awt.Point; | import java.awt.Point; | |||
import java.awt.Rectangle; | import java.awt.Rectangle; | |||
import java.awt.geom.AffineTransform; | import java.awt.geom.AffineTransform; | |||
import java.awt.geom.Point2D; | ||||
import java.awt.image.ColorModel; | import java.awt.image.ColorModel; | |||
import java.io.EOFException; | ||||
import java.io.IOException; | import java.io.IOException; | |||
import java.util.ArrayList; | ||||
import java.util.Collections; | ||||
import java.util.HashMap; | import java.util.HashMap; | |||
import java.util.List; | import java.util.List; | |||
import java.util.Map; | import java.util.Map; | |||
import javax.imageio.stream.ImageInputStream; | ||||
import javax.imageio.stream.MemoryCacheImageInputStream; | ||||
import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | ||||
import org.apache.pdfbox.cos.COSDictionary; | ||||
import org.apache.pdfbox.cos.COSStream; | ||||
import org.apache.pdfbox.pdmodel.common.PDRange; | ||||
import org.apache.pdfbox.util.Matrix; | import org.apache.pdfbox.util.Matrix; | |||
/** | /** | |||
* This class is extended in Type6ShadingContext and Type7ShadingContext. This | * This class is extended in Type6ShadingContext and Type7ShadingContext. This | |||
* was done as part of GSoC2014, Tilman Hausherr is the mentor. | * was done as part of GSoC2014, Tilman Hausherr is the mentor. | |||
* | * | |||
* @author Shaola Ren | * @author Shaola Ren | |||
*/ | */ | |||
abstract class PatchMeshesShadingContext extends TriangleBasedShadingContext | abstract class PatchMeshesShadingContext extends TriangleBasedShadingContext | |||
{ | { | |||
private static final Log LOG = LogFactory.getLog(PatchMeshesShadingContext.c lass); | ||||
/** | /** | |||
* patch list | * patch list | |||
*/ | */ | |||
private List<Patch> patchList = new ArrayList<Patch>(); | private List<Patch> patchList; | |||
/** | /** | |||
* Constructor creates an instance to be used for fill operations. | * Constructor creates an instance to be used for fill operations. | |||
* | * | |||
* @param shading the shading type to be used | * @param shading the shading type to be used | |||
* @param colorModel the color model to be used | * @param colorModel the color model to be used | |||
* @param xform transformation for user to device space | * @param xform transformation for user to device space | |||
* @param matrix the pattern matrix concatenated with that of the parent con tent stream | * @param matrix the pattern matrix concatenated with that of the parent con tent stream | |||
* @param deviceBounds device bounds | * @param deviceBounds device bounds | |||
* @param controlPoints number of control points, 12 for type 6 shading and 16 for type 7 shading | * @param controlPoints number of control points, 12 for type 6 shading and 16 for type 7 shading | |||
* @throws IOException if something went wrong | * @throws IOException if something went wrong | |||
*/ | */ | |||
protected PatchMeshesShadingContext(PDShadingType6 shading, ColorModel color Model, | protected PatchMeshesShadingContext(PDMeshBasedShadingType shading, ColorMod el colorModel, | |||
AffineTransform xform, Matrix matrix, Rectangle deviceBounds, | AffineTransform xform, Matrix matrix, Rectangle deviceBounds, | |||
int controlPoints) throws IOException | int controlPoints) throws IOException | |||
{ | { | |||
super(shading, colorModel, xform, matrix); | super(shading, colorModel, xform, matrix); | |||
patchList = collectPatches(shading, xform, matrix, controlPoints); | patchList = shading.collectPatches(xform, matrix, controlPoints); | |||
createPixelTable(deviceBounds); | createPixelTable(deviceBounds); | |||
} | } | |||
/** | ||||
* Create a patch list from a data stream, the returned list contains all th | ||||
e patches contained | ||||
* in the data stream. | ||||
* | ||||
* @param shadingType the shading type | ||||
* @param xform transformation for user to device space | ||||
* @param matrix the pattern matrix concatenated with that of the parent con | ||||
tent stream | ||||
* @param controlPoints number of control points, 12 for type 6 shading and | ||||
16 for type 7 shading | ||||
* @return the obtained patch list | ||||
* @throws IOException when something went wrong | ||||
*/ | ||||
final List<Patch> collectPatches(PDShadingType6 shadingType, AffineTransform | ||||
xform, | ||||
Matrix matrix, int controlPoints) throws IOException | ||||
{ | ||||
COSDictionary dict = shadingType.getCOSObject(); | ||||
if (!(dict instanceof COSStream)) | ||||
{ | ||||
return Collections.emptyList(); | ||||
} | ||||
PDRange rangeX = shadingType.getDecodeForParameter(0); | ||||
PDRange rangeY = shadingType.getDecodeForParameter(1); | ||||
if (Float.compare(rangeX.getMin(), rangeX.getMax()) == 0 || | ||||
Float.compare(rangeY.getMin(), rangeY.getMax()) == 0) | ||||
{ | ||||
return Collections.emptyList(); | ||||
} | ||||
int bitsPerFlag = shadingType.getBitsPerFlag(); | ||||
PDRange[] colRange = new PDRange[numberOfColorComponents]; | ||||
for (int i = 0; i < numberOfColorComponents; ++i) | ||||
{ | ||||
colRange[i] = shadingType.getDecodeForParameter(2 + i); | ||||
if (colRange[i] == null) | ||||
{ | ||||
throw new IOException("Range missing in shading /Decode entry"); | ||||
} | ||||
} | ||||
List<Patch> list = new ArrayList<Patch>(); | ||||
long maxSrcCoord = (long) Math.pow(2, bitsPerCoordinate) - 1; | ||||
long maxSrcColor = (long) Math.pow(2, bitsPerColorComponent) - 1; | ||||
COSStream cosStream = (COSStream) dict; | ||||
ImageInputStream mciis = new MemoryCacheImageInputStream(cosStream.creat | ||||
eInputStream()); | ||||
try | ||||
{ | ||||
Point2D[] implicitEdge = new Point2D[4]; | ||||
float[][] implicitCornerColor = new float[2][numberOfColorComponents | ||||
]; | ||||
byte flag = 0; | ||||
try | ||||
{ | ||||
flag = (byte) (mciis.readBits(bitsPerFlag) & 3); | ||||
} | ||||
catch (EOFException ex) | ||||
{ | ||||
LOG.error(ex); | ||||
} | ||||
boolean eof = false; | ||||
while (!eof) | ||||
{ | ||||
try | ||||
{ | ||||
boolean isFree = (flag == 0); | ||||
Patch current = readPatch(mciis, isFree, implicitEdge, impli | ||||
citCornerColor, | ||||
maxSrcCoord, maxSrcColor, rangeX, rangeY, colRange, | ||||
matrix, xform, controlPoints); | ||||
if (current == null) | ||||
{ | ||||
break; | ||||
} | ||||
list.add(current); | ||||
flag = (byte) (mciis.readBits(bitsPerFlag) & 3); | ||||
switch (flag) | ||||
{ | ||||
case 0: | ||||
break; | ||||
case 1: | ||||
implicitEdge = current.getFlag1Edge(); | ||||
implicitCornerColor = current.getFlag1Color(); | ||||
break; | ||||
case 2: | ||||
implicitEdge = current.getFlag2Edge(); | ||||
implicitCornerColor = current.getFlag2Color(); | ||||
break; | ||||
case 3: | ||||
implicitEdge = current.getFlag3Edge(); | ||||
implicitCornerColor = current.getFlag3Color(); | ||||
break; | ||||
default: | ||||
LOG.warn("bad flag: " + flag); | ||||
break; | ||||
} | ||||
} | ||||
catch (EOFException ex) | ||||
{ | ||||
eof = true; | ||||
} | ||||
} | ||||
} | ||||
finally | ||||
{ | ||||
mciis.close(); | ||||
} | ||||
return list; | ||||
} | ||||
/** | ||||
* Read a single patch from a data stream, a patch contains information of i | ||||
ts coordinates and | ||||
* color parameters. | ||||
* | ||||
* @param input the image source data stream | ||||
* @param isFree whether this is a free patch | ||||
* @param implicitEdge implicit edge when a patch is not free, otherwise it' | ||||
s not used | ||||
* @param implicitCornerColor implicit colors when a patch is not free, othe | ||||
rwise it's not used | ||||
* @param maxSrcCoord the maximum coordinate value calculated from source da | ||||
ta | ||||
* @param maxSrcColor the maximum color value calculated from source data | ||||
* @param rangeX range for coordinate x | ||||
* @param rangeY range for coordinate y | ||||
* @param colRange range for color | ||||
* @param matrix the pattern matrix concatenated with that of the parent con | ||||
tent stream | ||||
* @param xform transformation for user to device space | ||||
* @param controlPoints number of control points, 12 for type 6 shading and | ||||
16 for type 7 shading | ||||
* @return a single patch | ||||
* @throws IOException when something went wrong | ||||
*/ | ||||
protected Patch readPatch(ImageInputStream input, boolean isFree, Point2D[] | ||||
implicitEdge, | ||||
float[][] implicitCornerColor, long maxSrcCoord, l | ||||
ong maxSrcColor, | ||||
PDRange rangeX, PDRange rangeY, PDRange[] colRange | ||||
, Matrix matrix, | ||||
AffineTransform xform, int controlPoints) throws I | ||||
OException | ||||
{ | ||||
float[][] color = new float[4][numberOfColorComponents]; | ||||
Point2D[] points = new Point2D[controlPoints]; | ||||
int pStart = 4, cStart = 2; | ||||
if (isFree) | ||||
{ | ||||
pStart = 0; | ||||
cStart = 0; | ||||
} | ||||
else | ||||
{ | ||||
points[0] = implicitEdge[0]; | ||||
points[1] = implicitEdge[1]; | ||||
points[2] = implicitEdge[2]; | ||||
points[3] = implicitEdge[3]; | ||||
for (int i = 0; i < numberOfColorComponents; i++) | ||||
{ | ||||
color[0][i] = implicitCornerColor[0][i]; | ||||
color[1][i] = implicitCornerColor[1][i]; | ||||
} | ||||
} | ||||
try | ||||
{ | ||||
for (int i = pStart; i < controlPoints; i++) | ||||
{ | ||||
long x = input.readBits(bitsPerCoordinate); | ||||
long y = input.readBits(bitsPerCoordinate); | ||||
float px = interpolate(x, maxSrcCoord, rangeX.getMin(), rangeX.g | ||||
etMax()); | ||||
float py = interpolate(y, maxSrcCoord, rangeY.getMin(), rangeY.g | ||||
etMax()); | ||||
Point2D p = matrix.transformPoint(px, py); | ||||
xform.transform(p, p); | ||||
points[i] = p; | ||||
} | ||||
for (int i = cStart; i < 4; i++) | ||||
{ | ||||
for (int j = 0; j < numberOfColorComponents; j++) | ||||
{ | ||||
long c = input.readBits(bitsPerColorComponent); | ||||
color[i][j] = interpolate(c, maxSrcColor, colRange[j].getMin | ||||
(), | ||||
colRange[j].getMax()); | ||||
} | ||||
} | ||||
} | ||||
catch (EOFException ex) | ||||
{ | ||||
LOG.debug("EOF"); | ||||
return null; | ||||
} | ||||
return generatePatch(points, color); | ||||
} | ||||
/** | ||||
* Create a patch using control points and 4 corner color values, in | ||||
* Type6ShadingContext, a CoonsPatch is returned; in Type6ShadingContext, a | ||||
* TensorPatch is returned. | ||||
* | ||||
* @param points 12 or 16 control points | ||||
* @param color 4 corner colors | ||||
* @return a patch instance | ||||
*/ | ||||
abstract Patch generatePatch(Point2D[] points, float[][] color); | ||||
/** | ||||
* Get a point coordinate on a line by linear interpolation. | ||||
*/ | ||||
private float interpolate(float x, long maxValue, float rangeMin, float rang | ||||
eMax) | ||||
{ | ||||
return rangeMin + (x / maxValue) * (rangeMax - rangeMin); | ||||
} | ||||
@Override | @Override | |||
protected Map<Point, Integer> calcPixelTable(Rectangle deviceBounds) throws IOException | protected Map<Point, Integer> calcPixelTable(Rectangle deviceBounds) throws IOException | |||
{ | { | |||
Map<Point, Integer> map = new HashMap<Point, Integer>(); | Map<Point, Integer> map = new HashMap<Point, Integer>(); | |||
for (Patch it : patchList) | for (Patch it : patchList) | |||
{ | { | |||
super.calcPixelTable(it.listOfTriangles, map, deviceBounds); | super.calcPixelTable(it.listOfTriangles, map, deviceBounds); | |||
} | } | |||
return map; | return map; | |||
} | } | |||
End of changes. 9 change blocks. | ||||
237 lines changed or deleted | 4 lines changed or added |