You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/06/17 02:20:18 UTC
svn commit: r1603033 - in /pdfbox/trunk:
examples/src/main/java/org/apache/pdfbox/examples/util/
pdfbox/src/main/java/org/apache/pdfbox/cos/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/g...
Author: jahewson
Date: Tue Jun 17 00:20:17 2014
New Revision: 1603033
URL: http://svn.apache.org/r1603033
Log:
PDFBOX-2104: Implement transparency groups, as proposed by Petr Slaby
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendComposite.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendMode.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/NonSeparableBlendMode.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SeparableBlendMode.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SoftMaskPaint.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDGroup.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDSoftMask.java
Modified:
pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/util/PrintImageLocations.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDExtendedGraphicsState.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDGraphicsState.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GRestore.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GSave.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/pagedrawer/Invoke.java
pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java
pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java
Modified: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/util/PrintImageLocations.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/util/PrintImageLocations.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/util/PrintImageLocations.java (original)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/util/PrintImageLocations.java Tue Jun 17 00:20:17 2014
@@ -164,7 +164,7 @@ public class PrintImageLocations extends
else if(xobject instanceof PDFormXObject)
{
// save the graphics state
- getGraphicsStack().push( (PDGraphicsState)getGraphicsState().clone() );
+ saveGraphicsState();
PDFormXObject form = (PDFormXObject)xobject;
COSStream invoke = (COSStream)form.getCOSObject();
@@ -179,7 +179,7 @@ public class PrintImageLocations extends
processSubStream( pdResources, invoke );
// restore the graphics state
- setGraphicsState( (PDGraphicsState)getGraphicsStack().pop() );
+ restoreGraphicsState();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Tue Jun 17 00:20:17 2014
@@ -59,6 +59,7 @@ public final class COSName extends COSBa
public static final COSName AESV3 = new COSName("AESV3");
public static final COSName AIS = new COSName("AIS");
public static final COSName ALT = new COSName("Alt");
+ public static final COSName ALPHA = new COSName("Alpha");
public static final COSName ALTERNATE = new COSName("Alternate");
public static final COSName ANNOT = new COSName("Annot");
public static final COSName ANNOTS = new COSName("Annots");
@@ -84,6 +85,7 @@ public final class COSName extends COSBa
public static final COSName BASE_FONT = new COSName("BaseFont");
public static final COSName BASE_STATE = new COSName("BaseState");
public static final COSName BBOX = new COSName("BBox");
+ public static final COSName BC = new COSName("BC");
public static final COSName BITS_PER_COMPONENT = new COSName("BitsPerComponent");
public static final COSName BITS_PER_COORDINATE = new COSName("BitsPerCoordinate");
public static final COSName BITS_PER_FLAG = new COSName("BitsPerFlag");
@@ -91,6 +93,7 @@ public final class COSName extends COSBa
public static final COSName BLACK_IS_1 = new COSName("BlackIs1");
public static final COSName BLACK_POINT = new COSName("BlackPoint");
public static final COSName BLEED_BOX = new COSName("BleedBox");
+ public static final COSName BM = new COSName("BM");
public static final COSName BOUNDS = new COSName("Bounds");
public static final COSName BPC = new COSName("BPC");
public static final COSName BYTERANGE = new COSName("ByteRange");
@@ -119,10 +122,13 @@ public final class COSName extends COSBa
public static final COSName CLR_F = new COSName("ClrF");
public static final COSName CLR_FF = new COSName("ClrFf");
public static final COSName CMYK = new COSName("CMYK");
+ public static final COSName COLOR_BURN = new COSName("ColorBurn");
+ public static final COSName COLOR_DODGE = new COSName("ColorDodge");
public static final COSName COLORANTS = new COSName("Colorants");
public static final COSName COLORS = new COSName("Colors");
public static final COSName COLORSPACE = new COSName("ColorSpace");
public static final COSName COLUMNS = new COSName("Columns");
+ public static final COSName COMPATIBLE = new COSName("Compatible");
public static final COSName COMPONENTS = new COSName("Components");
public static final COSName CONTACT_INFO = new COSName("ContactInfo");
public static final COSName CONTENTS = new COSName("Contents");
@@ -136,6 +142,7 @@ public final class COSName extends COSBa
// D
public static final COSName D = new COSName("D");
public static final COSName DA = new COSName("DA");
+ public static final COSName DARKEN = new COSName("Darken");
public static final COSName DATE = new COSName("Date");
public static final COSName DCT_DECODE = new COSName("DCTDecode");
public static final COSName DCT_DECODE_ABBREVIATION = new COSName("DCT");
@@ -152,6 +159,7 @@ public final class COSName extends COSBa
public static final COSName DEVICEGRAY = new COSName("DeviceGray");
public static final COSName DEVICEN = new COSName("DeviceN");
public static final COSName DEVICERGB = new COSName("DeviceRGB");
+ public static final COSName DIFFERENCE = new COSName("Difference");
public static final COSName DIFFERENCES = new COSName("Differences");
public static final COSName DIGEST_METHOD = new COSName("DigestMethod");
public static final COSName DIGEST_RIPEMD160 = new COSName("RIPEMD160");
@@ -188,6 +196,7 @@ public final class COSName extends COSBa
public static final COSName ENCRYPT_META_DATA = new COSName("EncryptMetadata");
public static final COSName END_OF_LINE = new COSName("EndOfLine");
public static final COSName ENTRUST_PPKEF = new COSName("Entrust.PPKEF");
+ public static final COSName EXCLUSION = new COSName("Exclusion");
public static final COSName EXT_G_STATE = new COSName("ExtGState");
public static final COSName EXTEND = new COSName("Extend");
public static final COSName EXTENDS = new COSName("Extends");
@@ -227,9 +236,11 @@ public final class COSName extends COSBa
// G
public static final COSName G = new COSName("G");
public static final COSName GAMMA = new COSName("Gamma");
+ public static final COSName GROUP = new COSName("Group");
public static final COSName GTS_PDFA1 = new COSName("GTS_PDFA1");
// H
public static final COSName H = new COSName("H");
+ public static final COSName HARD_LIGHT = new COSName("HardLight");
public static final COSName HEIGHT = new COSName("Height");
public static final COSName HIDE_MENUBAR = new COSName("HideMenubar");
public static final COSName HIDE_TOOLBAR = new COSName("HideToolbar");
@@ -269,9 +280,11 @@ public final class COSName extends COSBa
public static final COSName LENGTH = new COSName("Length");
public static final COSName LENGTH1 = new COSName("Length1");
public static final COSName LENGTH2 = new COSName("Length2");
+ public static final COSName LIGHTEN = new COSName("Lighten");
public static final COSName LIMITS = new COSName("Limits");
public static final COSName LJ = new COSName("LJ");
public static final COSName LOCATION = new COSName("Location");
+ public static final COSName LUMINOSITY = new COSName("Luminosity");
public static final COSName LW = new COSName("LW");
public static final COSName LZW_DECODE = new COSName("LZWDecode");
public static final COSName LZW_DECODE_ABBREVIATION = new COSName("LZW");
@@ -292,6 +305,7 @@ public final class COSName extends COSBa
public static final COSName ML = new COSName("ML");
public static final COSName MM_TYPE1 = new COSName("MMType1");
public static final COSName MOD_DATE = new COSName("ModDate");
+ public static final COSName MULTIPLY = new COSName("Multiply");
// N
public static final COSName N = new COSName("N");
public static final COSName NAME = new COSName("Name");
@@ -300,6 +314,8 @@ public final class COSName extends COSBa
public static final COSName NM = new COSName("NM");
public static final COSName NON_EFONT_NO_WARN = new COSName("NonEFontNoWarn");
public static final COSName NON_FULL_SCREEN_PAGE_MODE = new COSName("NonFullScreenPageMode");
+ public static final COSName NONE = new COSName("None");
+ public static final COSName NORMAL = new COSName("Normal");
public static final COSName NUMS = new COSName("Nums");
// O
public static final COSName O = new COSName("O");
@@ -325,6 +341,7 @@ public final class COSName extends COSBa
public static final COSName OUTPUT_CONDITION_IDENTIFIER = new COSName("OutputConditionIdentifier");
public static final COSName OUTPUT_INTENT = new COSName("OutputIntent");
public static final COSName OUTPUT_INTENTS = new COSName("OutputIntents");
+ public static final COSName OVERLAY = new COSName("Overlay");
// P
public static final COSName P = new COSName("P");
public static final COSName PAGE = new COSName("Page");
@@ -378,6 +395,7 @@ public final class COSName extends COSBa
// S
public static final COSName S = new COSName("S");
public static final COSName SA = new COSName("SA");
+ public static final COSName SCREEN = new COSName("Screen");
public static final COSName SE = new COSName("SE");
public static final COSName SEPARATION = new COSName("Separation");
public static final COSName SET_F = new COSName("SetF");
@@ -389,6 +407,7 @@ public final class COSName extends COSBa
public static final COSName SIZE = new COSName("Size");
public static final COSName SM = new COSName("SM");
public static final COSName SMASK = new COSName("SMask");
+ public static final COSName SOFT_LIGHT = new COSName("SoftLight");
public static final COSName STANDARD_ENCODING = new COSName("StandardEncoding");
public static final COSName STATUS = new COSName("Status");
public static final COSName STD_CF = new COSName("StdCF");
@@ -415,7 +434,9 @@ public final class COSName extends COSBa
public static final COSName TITLE = new COSName("Title");
public static final COSName TK = new COSName("TK");
public static final COSName TO_UNICODE = new COSName("ToUnicode");
+ public static final COSName TR = new COSName("TR");
public static final COSName TRAPPED = new COSName("Trapped");
+ public static final COSName TRANSPARENCY = new COSName("Transparency");
public static final COSName TRIM_BOX = new COSName("TrimBox");
public static final COSName TRUE_TYPE = new COSName("TrueType");
public static final COSName TRUSTED_MODE = new COSName("TrustedMode");
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendComposite.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendComposite.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendComposite.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendComposite.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.pdmodel.graphics.blend;
+
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+import java.awt.CompositeContext;
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/**
+ * AWT composite for blend modes.
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public final class BlendComposite implements Composite
+{
+ /**
+ * Creates a blend composite
+ *
+ * @param blendMode Desired blend mode
+ * @param constantAlpha Constant alpha
+ */
+ public static Composite getInstance(BlendMode blendMode, float constantAlpha)
+ {
+ if (blendMode == BlendMode.NORMAL)
+ {
+ return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, constantAlpha);
+ }
+ else
+ {
+ return new BlendComposite(blendMode, constantAlpha);
+ }
+ }
+
+ // TODO - non-separable blending modes
+
+ private final BlendMode blendMode;
+ private final float constantAlpha;
+
+ private BlendComposite(BlendMode blendMode, float constantAlpha)
+ {
+ super();
+ this.blendMode = blendMode;
+ this.constantAlpha = constantAlpha;
+ }
+
+ public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel,
+ RenderingHints hints)
+ {
+ return new BlendCompositeContext(srcColorModel, dstColorModel, hints);
+ }
+
+ class BlendCompositeContext implements CompositeContext
+ {
+ private ColorModel srcColorModel;
+ private ColorModel dstColorModel;
+ private RenderingHints hints;
+
+ public BlendCompositeContext(ColorModel srcColorModel, ColorModel dstColorModel,
+ RenderingHints hints)
+ {
+ this.srcColorModel = srcColorModel;
+ this.dstColorModel = dstColorModel;
+ this.hints = hints;
+ }
+
+ public void dispose()
+ {
+ // nothing needed
+ }
+
+ public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
+ {
+ int x0 = src.getMinX();
+ int y0 = src.getMinY();
+ int width = Math.min(Math.min(src.getWidth(), dstIn.getWidth()), dstOut.getWidth());
+ int height = Math.min(Math.min(src.getHeight(), dstIn.getHeight()), dstOut.getHeight());
+ int x1 = x0 + width;
+ int y1 = y0 + height;
+ int dstInXShift = dstIn.getMinX() - x0;
+ int dstInYShift = dstIn.getMinY() - y0;
+ int dstOutXShift = dstOut.getMinX() - x0;
+ int dstOutYShift = dstOut.getMinY() - y0;
+
+ ColorSpace srcColorSpace = srcColorModel.getColorSpace();
+ int numSrcColorComponents = srcColorModel.getNumColorComponents();
+ int numSrcComponents = src.getNumBands();
+ boolean srcHasAlpha = (numSrcComponents > numSrcColorComponents);
+ ColorSpace dstColorSpace = dstColorModel.getColorSpace();
+ int numDstColorComponents = dstColorModel.getNumColorComponents();
+ int numDstComponents = dstIn.getNumBands();
+ boolean dstHasAlpha = (numDstComponents > numDstColorComponents);
+
+ int colorSpaceType = dstColorSpace.getType();
+ boolean subtractive = (colorSpaceType != ColorSpace.TYPE_RGB)
+ && (colorSpaceType != ColorSpace.TYPE_GRAY);
+
+ boolean blendModeIsSeparable = blendMode instanceof SeparableBlendMode;
+ SeparableBlendMode separableBlendMode = blendModeIsSeparable ?
+ (SeparableBlendMode) blendMode : null;
+
+ boolean needsColorConversion = !srcColorSpace.equals(dstColorSpace);
+
+ Object srcPixel = null;
+ Object dstPixel = null;
+ float[] srcComponents = new float[numSrcComponents];
+ float[] dstComponents = new float[numDstComponents];
+
+ float[] srcColor = new float[numSrcColorComponents];
+ float[] srcConverted;
+
+ for (int y = y0; y < y1; y++)
+ {
+ for (int x = x0; x < x1; x++)
+ {
+ srcPixel = src.getDataElements(x, y, srcPixel);
+ dstPixel = dstIn.getDataElements(dstInXShift + x, dstInYShift + y, dstPixel);
+
+ srcComponents = srcColorModel.getNormalizedComponents(srcPixel, srcComponents,
+ 0);
+ dstComponents = dstColorModel.getNormalizedComponents(dstPixel, dstComponents,
+ 0);
+
+ float srcAlpha = srcHasAlpha ? srcComponents[numSrcColorComponents] : 1.0f;
+ float dstAlpha = dstHasAlpha ? dstComponents[numDstColorComponents] : 1.0f;
+
+ srcAlpha = srcAlpha * constantAlpha;
+
+ float resultAlpha = dstAlpha + srcAlpha - srcAlpha * dstAlpha;
+ float srcAlphaRatio = (resultAlpha > 0) ? srcAlpha / resultAlpha : 0;
+
+ // convert color
+ System.arraycopy(srcComponents, 0, srcColor, 0, numSrcColorComponents);
+ if (needsColorConversion)
+ {
+ // TODO - very very slow - Hash results???
+ float[] cieXYZ = srcColorSpace.toCIEXYZ(srcColor);
+ srcConverted = dstColorSpace.fromCIEXYZ(cieXYZ);
+ }
+ else
+ {
+ srcConverted = srcColor;
+ }
+
+ if (separableBlendMode != null)
+ {
+ for (int k = 0; k < numDstColorComponents; k++)
+ {
+ float srcValue = srcConverted[k];
+ float dstValue = dstComponents[k];
+
+ if (subtractive)
+ {
+ srcValue = 1 - srcValue;
+ dstValue = 1 - dstValue;
+ }
+
+ float value = separableBlendMode.blendChannel(srcValue, dstValue);
+ value = srcValue + dstAlpha * (value - srcValue);
+ value = dstValue + srcAlphaRatio * (value - dstValue);
+
+ if (subtractive)
+ {
+ value = 1 - value;
+ }
+
+ dstComponents[k] = value;
+ }
+ }
+ else
+ {
+ // TODO - nonseparable modes
+ }
+
+ if (dstHasAlpha)
+ {
+ dstComponents[numDstColorComponents] = resultAlpha;
+ }
+
+ dstPixel = dstColorModel.getDataElements(dstComponents, 0, dstPixel);
+ dstOut.setDataElements(dstOutXShift + x, dstOutYShift + y, dstPixel);
+ }
+ }
+ }
+ }
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendMode.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendMode.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendMode.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/BlendMode.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,183 @@
+package org.apache.pdfbox.pdmodel.graphics.blend;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSName;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Blend mode.
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public abstract class BlendMode
+{
+ private static final Map<COSName, BlendMode> BLEND_MODES = createBlendModeMap();
+
+ private static Map<COSName, BlendMode> createBlendModeMap()
+ {
+ Map<COSName, BlendMode> map = new HashMap<COSName, BlendMode>();
+ map.put(COSName.NORMAL, BlendMode.NORMAL);
+ map.put(COSName.COMPATIBLE, BlendMode.COMPATIBLE);
+ map.put(COSName.MULTIPLY, BlendMode.MULTIPLY);
+ map.put(COSName.SCREEN, BlendMode.SCREEN);
+ map.put(COSName.OVERLAY, BlendMode.OVERLAY);
+ map.put(COSName.DARKEN, BlendMode.DARKEN);
+ map.put(COSName.LIGHTEN, BlendMode.LIGHTEN);
+ map.put(COSName.COLOR_DODGE, BlendMode.COLOR_DODGE);
+ map.put(COSName.COLOR_BURN, BlendMode.COLOR_BURN);
+ map.put(COSName.HARD_LIGHT, BlendMode.HARD_LIGHT);
+ map.put(COSName.SOFT_LIGHT, BlendMode.SOFT_LIGHT);
+ map.put(COSName.DIFFERENCE, BlendMode.DIFFERENCE);
+ map.put(COSName.EXCLUSION, BlendMode.EXCLUSION);
+ // TODO - non-separable blending modes
+ return map;
+ }
+
+ /**
+ * Determines the blend mode from the BM entry in the COS ExtGState.
+ *
+ * @param cosBlendMode name or array
+ * @return blending mode
+ */
+ public static BlendMode getInstance(COSBase cosBlendMode)
+ {
+ BlendMode result = null;
+ if (cosBlendMode instanceof COSName)
+ {
+ result = BLEND_MODES.get(cosBlendMode);
+ }
+ else if (cosBlendMode instanceof COSArray)
+ {
+ COSArray cosBlendModeArray = (COSArray) cosBlendMode;
+ for (int i = 0; i < cosBlendModeArray.size(); i++)
+ {
+ result = BLEND_MODES.get(cosBlendModeArray.get(i));
+ if (result != null)
+ {
+ break;
+ }
+ }
+ }
+ if (result != null)
+ {
+ return result;
+ }
+ return BlendMode.COMPATIBLE;
+ }
+
+ public static SeparableBlendMode NORMAL = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return srcValue;
+ }
+ };
+
+ public static SeparableBlendMode COMPATIBLE = NORMAL;
+
+ public static SeparableBlendMode MULTIPLY = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return srcValue * dstValue;
+ }
+ };
+
+ public static SeparableBlendMode SCREEN = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return srcValue + dstValue - srcValue * dstValue;
+ }
+ };
+
+ public static SeparableBlendMode OVERLAY = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return (dstValue <= 0.5) ? 2 * dstValue * srcValue : 2 * (srcValue + dstValue - srcValue
+ * dstValue) - 1;
+ }
+ };
+
+ public static SeparableBlendMode DARKEN = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return Math.min(srcValue, dstValue);
+ }
+ };
+
+ public static SeparableBlendMode LIGHTEN = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return Math.max(srcValue, dstValue);
+ }
+ };
+
+ public static SeparableBlendMode COLOR_DODGE = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return (srcValue < 1) ? Math.min(1, dstValue / (1 - srcValue)) : 1;
+ }
+ };
+
+ public static SeparableBlendMode COLOR_BURN = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return (srcValue > 0) ? 1 - Math.min(1, (1 - dstValue) / srcValue) : 0;
+ }
+ };
+
+ public static SeparableBlendMode HARD_LIGHT = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return (srcValue <= 0.5) ? 2 * dstValue * srcValue :
+ 2 * (srcValue + dstValue - srcValue * dstValue) - 1;
+ }
+ };
+
+ public static SeparableBlendMode SOFT_LIGHT = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ if (srcValue <= 0.5)
+ {
+ return dstValue - (1 - 2 * srcValue) * dstValue * (1 - dstValue);
+ }
+ else
+ {
+ float D = (dstValue <= 0.25) ? ((16 * dstValue - 12) * dstValue + 4) * dstValue
+ : (float) Math .sqrt(dstValue);
+ return dstValue + (2 * srcValue - 1) * (D - dstValue);
+ }
+ }
+ };
+
+ public static SeparableBlendMode DIFFERENCE = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return Math.abs(dstValue - srcValue);
+ }
+ };
+
+ public static SeparableBlendMode EXCLUSION = new SeparableBlendMode()
+ {
+ public float blendChannel(float srcValue, float dstValue)
+ {
+ return dstValue + srcValue - 2 * dstValue * srcValue;
+ }
+ };
+
+ BlendMode()
+ {
+ }
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/NonSeparableBlendMode.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/NonSeparableBlendMode.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/NonSeparableBlendMode.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/NonSeparableBlendMode.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,15 @@
+package org.apache.pdfbox.pdmodel.graphics.blend;
+
+/**
+ * Non-separable blend mode (supports blend function).
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public abstract class NonSeparableBlendMode extends BlendMode
+{
+ NonSeparableBlendMode()
+ {
+ }
+
+ public abstract void blend(float[] srcValues, float[] dstValues, float[] result);
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SeparableBlendMode.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SeparableBlendMode.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SeparableBlendMode.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SeparableBlendMode.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,15 @@
+package org.apache.pdfbox.pdmodel.graphics.blend;
+
+/**
+ * Separable blend mode (support blendChannel)
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public abstract class SeparableBlendMode extends BlendMode
+{
+ SeparableBlendMode()
+ {
+ }
+
+ public abstract float blendChannel(float srcValue, float dstValue);
+}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SoftMaskPaint.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SoftMaskPaint.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SoftMaskPaint.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/blend/SoftMaskPaint.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.pdmodel.graphics.blend;
+
+import java.awt.Paint;
+import java.awt.PaintContext;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Transparency;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorConvertOp;
+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;
+
+/**
+ * AWT Paint that adds a soft mask to the alpha channel of the existing parent paint. If the parent
+ * paint does not have an alpha channel, a new raster is created.
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public final class SoftMaskPaint implements Paint
+{
+ private final Paint parentPaint;
+ private final Raster softMaskRaster;
+
+ /**
+ * Applies the soft mask to the parent.
+ */
+ public SoftMaskPaint(Paint parentPaint, Raster softMaskRaster)
+ {
+ this.parentPaint = parentPaint;
+ this.softMaskRaster = softMaskRaster;
+ }
+
+ public int getTransparency()
+ {
+ return Transparency.TRANSLUCENT;
+ }
+
+ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+ Rectangle2D userBounds, AffineTransform at, RenderingHints hints)
+ {
+ try
+ {
+ PaintContext parentContext = parentPaint.createContext(null, deviceBounds, userBounds,
+ at, hints);
+ return new Context(parentContext);
+ }
+ catch (IOException e)
+ {
+ return null; // context cannot be created
+ }
+ }
+
+ private class Context implements PaintContext
+ {
+ private PaintContext parentContext;
+ private final ColorModel colorModel;
+ private final int numColorComponents;
+ private final ColorModel parentColorModel;
+
+ public Context(PaintContext parentContext) throws IOException
+ {
+ this.parentContext = parentContext;
+ parentColorModel = parentContext.getColorModel();
+ if (parentContext.getColorModel().hasAlpha())
+ {
+ colorModel = parentColorModel;
+ }
+ else
+ {
+ colorModel = new ComponentColorModel(parentContext.getColorModel()
+ .getColorSpace(), true, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+ }
+ numColorComponents = colorModel.getNumColorComponents();
+ }
+
+ public ColorModel getColorModel()
+ {
+ return colorModel;
+ }
+
+ public Raster getRaster(int x, int y, int w, int h)
+ {
+ Raster parentRaster = parentContext.getRaster(x, y, w, h);
+
+ // getRaster can return the raster with origin (0,0) even if we applied for (x,y)
+ int parentMinX = parentRaster.getMinX();
+ int parentMinY = parentRaster.getMinY();
+
+ WritableRaster result;
+ if (parentRaster instanceof WritableRaster)
+ {
+ if (parentColorModel.equals(colorModel))
+ {
+ result = parentRaster.createCompatibleWritableRaster();
+ result.setDataElements(-parentMinX, -parentMinY, parentRaster);
+ }
+ else
+ {
+ BufferedImage parentImage = new BufferedImage(parentColorModel,
+ (WritableRaster) parentRaster,
+ parentColorModel.isAlphaPremultiplied(), null);
+ result = Raster.createWritableRaster(
+ colorModel.createCompatibleSampleModel(w, h), new Point(0, 0));
+ BufferedImage resultImage = new BufferedImage(colorModel, result, false, null);
+ resultImage.getGraphics().drawImage(parentImage, 0, 0, null);
+ }
+ }
+ else
+ {
+ result = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, getColorModel()
+ .getNumComponents(), new Point(0, 0));
+ ColorConvertOp colorConvertOp = new ColorConvertOp(
+ parentColorModel.getColorSpace(), colorModel.getColorSpace(), null);
+ colorConvertOp.filter(parentRaster, result);
+ }
+
+ int softMaskMinX = softMaskRaster.getMinX();
+ int softMaskMinY = softMaskRaster.getMinY();
+ int softMaskMaxX = softMaskMinX + softMaskRaster.getWidth();
+ int softMaskMaxY = softMaskMinY + softMaskRaster.getHeight();
+
+ for (int j = 0; j < h; j++)
+ {
+ for (int i = 0; i < w; i++)
+ {
+ int rx = x + i;
+ int ry = y + j;
+
+ int alpha;
+ if ((rx >= softMaskMinX) && (rx < softMaskMaxX) && (ry >= softMaskMinY)
+ && (ry < softMaskMaxY))
+ {
+ alpha = softMaskRaster.getSample(Math.round(rx), Math.round(ry), 0);
+ }
+ else
+ {
+ alpha = 0;
+ }
+ alpha = alpha * result.getSample(i, j, numColorComponents) / 255;
+ result.setSample(i, j, numColorComponents, alpha);
+ }
+ }
+
+ return result;
+ }
+
+ public void dispose()
+ {
+ // do nothing
+ }
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDFormXObject.java Tue Jun 17 00:20:17 2014
@@ -22,12 +22,10 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSArray;
-import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSNumber;
-import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
@@ -61,6 +59,8 @@ public final class PDFormXObject extends
// name of XObject in resources, to prevent recursion
private String name;
+ private PDGroup group;
+
/**
* Creates a Form XObject for reading.
* @param stream The XObject stream
@@ -109,6 +109,23 @@ public final class PDFormXObject extends
}
/**
+ * Returns group descriptor...
+ *
+ * @return
+ */
+ public PDGroup getGroup() {
+ if( group == null )
+ {
+ COSDictionary dic = (COSDictionary) getCOSStream().getDictionaryObject(COSName.GROUP);
+ if( dic != null )
+ {
+ group = new PDGroup(dic);
+ }
+ }
+ return group;
+ }
+
+ /**
* This will get the resources at this page and not look up the hierarchy.
* This attribute is inheritable, and findResources() should probably used.
* This will return null if no resources are available at this level.
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDGroup.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDGroup.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDGroup.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/form/PDGroup.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.pdmodel.graphics.form;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.common.COSObjectable;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+
+/**
+ * Transparency group.
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public final class PDGroup implements COSObjectable
+{
+ private COSDictionary dictionary;
+ private COSName subType;
+ private PDColorSpace colorSpace;
+
+ /**
+ * Creates a group object from a given dictionary
+ * @param dic {@link COSDictionary} object
+ */
+ public PDGroup(COSDictionary dic)
+ {
+ dictionary = dic;
+ }
+
+ public COSBase getCOSObject()
+ {
+ return dictionary;
+ }
+
+ public COSDictionary getCOSDictionary()
+ {
+ return dictionary;
+ }
+
+ /**
+ * Returns the groups's subtype, should be "Transparency".
+ */
+ public COSName getSubType()
+ {
+ if (subType == null)
+ {
+ subType = (COSName) getCOSDictionary().getDictionaryObject(COSName.S);
+ }
+ return subType;
+ }
+
+ /**
+ * Returns the blending color space
+ * @return color space
+ * @throws IOException
+ */
+ public PDColorSpace getColorSpace() throws IOException
+ {
+ if (colorSpace == null)
+ {
+ colorSpace = PDColorSpace.create(getCOSDictionary().getDictionaryObject(
+ COSName.COLORSPACE));
+ }
+ return colorSpace;
+ }
+
+ /**
+ * Returns true if this group is isolated. Isolated groups begin with the fully transparent
+ * image, non-isolated begin with the current backdrop.
+ */
+ public boolean isIsolated()
+ {
+ return getCOSDictionary().getBoolean(COSName.I, false);
+ }
+
+ /**
+ * Returns true if this group is a knockout. A knockout group blends with original backdrop,
+ * a non-knockout group blends with the current backdrop.
+ */
+ public boolean isKnockout()
+ {
+ return getCOSDictionary().getBoolean(COSName.K, false);
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDExtendedGraphicsState.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDExtendedGraphicsState.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDExtendedGraphicsState.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDExtendedGraphicsState.java Tue Jun 17 00:20:17 2014
@@ -16,19 +16,18 @@
*/
package org.apache.pdfbox.pdmodel.graphics.state;
+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.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSNumber;
-
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.pdmodel.graphics.PDFontSetting;
import org.apache.pdfbox.pdmodel.graphics.PDLineDashPattern;
-
-import java.io.IOException;
-
+import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
/**
* This class represents the graphics state dictionary that is stored in the PDF document.
@@ -151,6 +150,14 @@ public class PDExtendedGraphicsState imp
{
gs.getTextState().setKnockoutFlag( getTextKnockoutFlag() );
}
+ else if( key.equals( COSName.SMASK ) )
+ {
+ gs.setSoftMask(getSoftMask());
+ }
+ else if( key.equals( COSName.BM ) )
+ {
+ gs.setBlendMode( getBlendMode() );
+ }
}
}
@@ -283,7 +290,7 @@ public class PDExtendedGraphicsState imp
*/
public void setLineDashPattern( PDLineDashPattern dashPattern )
{
- graphicsState.setItem( COSName.D, dashPattern.getCOSObject() );
+ graphicsState.setItem(COSName.D, dashPattern.getCOSObject());
}
/**
@@ -303,7 +310,7 @@ public class PDExtendedGraphicsState imp
*/
public void setRenderingIntent( String ri )
{
- graphicsState.setName( "RI", ri );
+ graphicsState.setName("RI", ri);
}
/**
@@ -313,7 +320,7 @@ public class PDExtendedGraphicsState imp
*/
public boolean getStrokingOverprintControl()
{
- return graphicsState.getBoolean( COSName.OP, false );
+ return graphicsState.getBoolean(COSName.OP, false);
}
/**
@@ -323,7 +330,7 @@ public class PDExtendedGraphicsState imp
*/
public void setStrokingOverprintControl( boolean op )
{
- graphicsState.setBoolean( COSName.OP, op );
+ graphicsState.setBoolean(COSName.OP, op);
}
/**
@@ -354,7 +361,7 @@ public class PDExtendedGraphicsState imp
*/
public Float getOverprintMode()
{
- return getFloatItem( COSName.OPM );
+ return getFloatItem(COSName.OPM);
}
/**
@@ -364,7 +371,7 @@ public class PDExtendedGraphicsState imp
*/
public void setOverprintMode( Float overprintMode )
{
- setFloatItem( COSName.OPM, overprintMode );
+ setFloatItem(COSName.OPM, overprintMode);
}
/**
@@ -390,7 +397,7 @@ public class PDExtendedGraphicsState imp
*/
public void setFontSetting( PDFontSetting fs )
{
- graphicsState.setItem( COSName.FONT, fs );
+ graphicsState.setItem(COSName.FONT, fs);
}
/**
@@ -410,7 +417,7 @@ public class PDExtendedGraphicsState imp
*/
public void setFlatnessTolerance( Float flatness )
{
- setFloatItem( COSName.FL, flatness );
+ setFloatItem(COSName.FL, flatness);
}
/**
@@ -440,7 +447,7 @@ public class PDExtendedGraphicsState imp
*/
public boolean getAutomaticStrokeAdjustment()
{
- return graphicsState.getBoolean( COSName.SA,false );
+ return graphicsState.getBoolean(COSName.SA, false);
}
/**
@@ -450,7 +457,7 @@ public class PDExtendedGraphicsState imp
*/
public void setAutomaticStrokeAdjustment( boolean sa )
{
- graphicsState.setBoolean( COSName.SA, sa );
+ graphicsState.setBoolean(COSName.SA, sa);
}
/**
@@ -460,7 +467,7 @@ public class PDExtendedGraphicsState imp
*/
public Float getStrokingAlpaConstant()
{
- return getFloatItem( COSName.CA );
+ return getFloatItem(COSName.CA);
}
/**
@@ -470,7 +477,7 @@ public class PDExtendedGraphicsState imp
*/
public void setStrokingAlphaConstant( Float alpha )
{
- setFloatItem( COSName.CA, alpha );
+ setFloatItem(COSName.CA, alpha);
}
/**
@@ -500,7 +507,7 @@ public class PDExtendedGraphicsState imp
*/
public boolean getAlphaSourceFlag()
{
- return graphicsState.getBoolean( COSName.AIS, false );
+ return graphicsState.getBoolean(COSName.AIS, false);
}
/**
@@ -510,10 +517,25 @@ public class PDExtendedGraphicsState imp
*/
public void setAlphaSourceFlag( boolean alpha )
{
- graphicsState.setBoolean( COSName.AIS, alpha );
+ graphicsState.setBoolean(COSName.AIS, alpha);
}
/**
+ * Returns the blending mode stored in the COS dictionary
+ *
+ * @return
+ */
+ public BlendMode getBlendMode() {
+ return BlendMode.getInstance(graphicsState.getDictionaryObject(COSName.BM));
+ }
+
+ public PDSoftMask getSoftMask() {
+ return PDSoftMask.create(graphicsState.getDictionaryObject(COSName.SMASK));
+ }
+
+ /**
+
+ /**
* This will get the text knockout flag.
*
* @return The text knockout flag.
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDGraphicsState.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDGraphicsState.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDGraphicsState.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDGraphicsState.java Tue Jun 17 00:20:17 2014
@@ -16,13 +16,18 @@
*/
package org.apache.pdfbox.pdmodel.graphics.state;
-import java.awt.*;
+import java.awt.BasicStroke;
+import java.awt.Composite;
+import java.awt.Rectangle;
+import java.awt.Shape;
import java.awt.geom.GeneralPath;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDLineDashPattern;
+import org.apache.pdfbox.pdmodel.graphics.blend.BlendComposite;
+import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray;
@@ -78,6 +83,9 @@ public class PDGraphicsState implements
private GeneralPath currentClippingPath;
+ private BlendMode blendMode = BlendMode.COMPATIBLE;
+ private PDSoftMask softMask;
+
/**
* Default constructor.
*/
@@ -281,6 +289,49 @@ public class PDGraphicsState implements
}
/**
+ * returns the current softmask
+ *
+ * @return softMask
+ */
+ public PDSoftMask getSoftMask()
+ {
+ return softMask;
+ }
+
+
+ /**
+ * Sets the current soft mask
+ *
+ * @param softMask
+ */
+ public void setSoftMask(PDSoftMask softMask)
+ {
+ this.softMask = softMask;
+ }
+
+ /**
+ * Returns the current blend mode
+ *
+ * @return
+ */
+ public BlendMode getBlendMode()
+ {
+ return blendMode;
+ }
+
+ /**
+ * Sets the blend mode in the current graphics state
+ *
+ * @param blendMode
+ */
+ public void setBlendMode(BlendMode blendMode)
+ {
+ this.blendMode = blendMode;
+ }
+
+ /**
+
+ /**
* get the value of the overprint property.
*
* @return The value of the overprint parameter.
@@ -567,13 +618,13 @@ public class PDGraphicsState implements
return currentClippingPath;
}
- public Composite getStrokeJavaComposite() {
-
- return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) alphaConstants);
+ public Composite getStrokeJavaComposite()
+ {
+ return BlendComposite.getInstance(blendMode, (float) alphaConstants);
}
- public Composite getNonStrokeJavaComposite() {
-
- return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) nonStrokingAlphaConstants);
+ public Composite getNonStrokeJavaComposite()
+ {
+ return BlendComposite.getInstance(blendMode, (float) nonStrokingAlphaConstants);
}
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDSoftMask.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDSoftMask.java?rev=1603033&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDSoftMask.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/state/PDSoftMask.java Tue Jun 17 00:20:17 2014
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+package org.apache.pdfbox.pdmodel.graphics.state;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.COSObjectable;
+import org.apache.pdfbox.pdmodel.common.function.PDFunction;
+import org.apache.pdfbox.pdmodel.graphics.PDXObject;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
+
+/**
+ * Soft mask.
+ *
+ * @author Kühn & Weyh Software, GmbH
+ */
+public final class PDSoftMask implements COSObjectable
+{
+ /**
+ * Creates a new soft mask.
+ *
+ * @param dictionary SMask
+ */
+ public static PDSoftMask create(COSBase dictionary)
+ {
+ if (dictionary instanceof COSName)
+ {
+ if (COSName.NONE.equals(dictionary))
+ {
+ return null;
+ }
+ else
+ {
+ LOG.warn("Invalid SMask " + dictionary);
+ return null;
+ }
+ }
+ else if (dictionary instanceof COSDictionary)
+ {
+ return new PDSoftMask((COSDictionary) dictionary);
+ }
+ else
+ {
+ LOG.warn("Invalid SMask " + dictionary);
+ return null;
+ }
+ }
+
+ private static final Log LOG = LogFactory.getLog(PDSoftMask.class);
+
+ private COSDictionary dictionary;
+ private COSName subType = null;
+ private PDFormXObject group = null;
+ private COSArray backdropColor = null;
+ private PDFunction transferFunction = null;
+
+ /**
+ * Creates a new soft mask.
+ */
+ public PDSoftMask(COSDictionary dictionary)
+ {
+ super();
+ this.dictionary = dictionary;
+ }
+
+ public COSBase getCOSObject()
+ {
+ return dictionary;
+ }
+
+ public COSDictionary getCOSDictionary()
+ {
+ return dictionary;
+ }
+
+ /**
+ * Returns the subtype of the soft mask (Alpha, Luminosity) - S entry
+ */
+ public COSName getSubType()
+ {
+ if (subType == null)
+ {
+ subType = (COSName) getCOSDictionary().getDictionaryObject(COSName.S);
+ }
+ return subType;
+ }
+
+ /**
+ * Returns the G entry of the soft mask object
+ *
+ * @return form containing the transparency group
+ * @throws IOException
+ */
+ public PDFormXObject getGroup() throws IOException
+ {
+ if (group == null)
+ {
+ COSBase cosGroup = getCOSDictionary().getDictionaryObject(COSName.G);
+ if (cosGroup != null)
+ {
+ group = (PDFormXObject) PDXObject
+ .createXObject(cosGroup, COSName.G.getName(), null);
+ }
+ }
+ return group;
+ }
+
+ /**
+ * Returns the backdrop color.
+ */
+ public COSArray getBackdropColor()
+ {
+ if (backdropColor == null)
+ {
+ backdropColor = (COSArray) getCOSDictionary().getDictionaryObject(COSName.BC);
+ }
+ return backdropColor;
+ }
+
+ /**
+ * Returns the transfer function.
+ */
+ public PDFunction getTransferFunction() throws IOException
+ {
+ if (transferFunction == null)
+ {
+ COSBase cosTF = getCOSDictionary().getDictionaryObject(COSName.TR);
+ if (cosTF != null)
+ {
+ transferFunction = PDFunction.create(cosTF);
+ }
+ }
+ return transferFunction;
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java Tue Jun 17 00:20:17 2014
@@ -25,6 +25,8 @@ import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.TexturePaint;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
@@ -32,6 +34,10 @@ import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
@@ -64,20 +70,24 @@ import org.apache.pdfbox.pdmodel.font.PD
import org.apache.pdfbox.pdmodel.font.PDType1CFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.PDType3Font;
-import org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState;
import org.apache.pdfbox.pdmodel.graphics.PDLineDashPattern;
+import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
+import org.apache.pdfbox.pdmodel.graphics.state.PDSoftMask;
+import org.apache.pdfbox.pdmodel.graphics.blend.SoftMaskPaint;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.graphics.pattern.PDTilingPattern;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShading;
+import org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState;
+import org.apache.pdfbox.pdmodel.graphics.state.PDTextState;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
-import org.apache.pdfbox.pdmodel.graphics.state.PDTextState;
+import org.apache.pdfbox.text.TextPosition;
import org.apache.pdfbox.util.Matrix;
import org.apache.pdfbox.util.PDFStreamEngine;
import org.apache.pdfbox.util.ResourceLoader;
-import org.apache.pdfbox.text.TextPosition;
/**
* This will paint a page in a PDF document to a graphics context.
@@ -397,7 +407,7 @@ public class PageDrawer extends PDFStrea
if (stream != null)
{
// save the current graphics state and matrices
- getGraphicsStack().push((PDGraphicsState) getGraphicsState().clone());
+ saveGraphicsState();
Matrix textMatrix = getTextMatrix();
Matrix textLineMatrix = getTextLineMatrix();
@@ -407,7 +417,7 @@ public class PageDrawer extends PDFStrea
processSubStream(font.getType3Resources(), stream);
// restore the saved graphics state and matrices
- setGraphicsState(getGraphicsStack().pop());
+ restoreGraphicsState();
setTextLineMatrix(textLineMatrix);
setTextMatrix(textMatrix);
@@ -623,11 +633,49 @@ public class PageDrawer extends PDFStrea
return linePath;
}
+ /**
+ * Generates awt raster for a soft mask
+ *
+ * @param context
+ * @return
+ * @throws IOException
+ */
+ private Raster createSoftMaskRaster(PDSoftMask softMask) throws IOException
+ {
+ PageDrawer.Group result = createPageDrawerGroup(softMask.getGroup());
+ COSName sMaskSubType = softMask.getSubType();
+ if (COSName.ALPHA.equals(sMaskSubType))
+ {
+ return result.getAlphaRaster();
+ }
+ else if (COSName.LUMINOSITY.equals(sMaskSubType))
+ {
+ return result.getLuminosityRaster();
+ }
+ else
+ {
+ throw new IOException("Invalid soft mask subtype.");
+ }
+ }
+
+ private Paint applySoftMaskToPaint(Paint parentPaint, PDSoftMask softMask) throws IOException
+ {
+ if (softMask != null)
+ {
+ return new SoftMaskPaint(parentPaint, createSoftMaskRaster(softMask));
+ }
+ else
+ {
+ return parentPaint;
+ }
+ }
+
// returns the stroking AWT Paint
private Paint getStrokingPaint() throws IOException
{
- return getGraphicsState().getStrokingColorSpace()
- .toPaint(renderer, getGraphicsState().getStrokingColor(), pageHeight);
+ PDGraphicsState graphicsState = getGraphicsState();
+ return applySoftMaskToPaint(graphicsState.getStrokingColorSpace()
+ .toPaint(renderer, graphicsState.getStrokingColor(), pageHeight), graphicsState.getSoftMask());
}
// returns the non-stroking AWT Paint
@@ -816,16 +864,34 @@ public class PageDrawer extends PDFStrea
* @param at The transformation to use when drawing.
*
*/
- public void drawImage(Image awtImage, AffineTransform at)
+ public void drawImage(Image awtImage, AffineTransform at) throws IOException
{
graphics.setComposite(getGraphicsState().getNonStrokeJavaComposite());
graphics.setClip(getGraphicsState().getCurrentClippingPath());
- int width = awtImage.getWidth(null);
- int height = awtImage.getHeight(null);
- AffineTransform imageTransform = new AffineTransform(at);
- imageTransform.scale(1.0 / width, -1.0 / height);
- imageTransform.translate(0, -height);
- graphics.drawImage(awtImage, imageTransform, null);
+ PDSoftMask softMask = getGraphicsState().getSoftMask();
+ if( softMask != null )
+ {
+ AffineTransform imageTransform = new AffineTransform(at);
+ imageTransform.scale(1, -1);
+ imageTransform.translate(0, -1);
+ Paint awtPaint = new TexturePaint((BufferedImage)awtImage,
+ new Rectangle2D.Double(imageTransform.getTranslateX(), imageTransform.getTranslateY(),
+ imageTransform.getScaleX(), imageTransform.getScaleY()));
+ awtPaint = applySoftMaskToPaint(awtPaint, softMask);
+ graphics.setPaint(awtPaint);
+ graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ Rectangle2D unitRect = new Rectangle2D.Float(0, 0, 1, 1);
+ graphics.fill(at.createTransformedShape(unitRect));
+ }
+ else
+ {
+ int width = awtImage.getWidth(null);
+ int height = awtImage.getHeight(null);
+ AffineTransform imageTransform = new AffineTransform(at);
+ imageTransform.scale(1.0 / width, -1.0 / height);
+ imageTransform.translate(0, -height);
+ graphics.drawImage(awtImage, imageTransform, null);
+ }
}
/**
@@ -846,4 +912,191 @@ public class PageDrawer extends PDFStrea
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
graphics.fill(getGraphicsState().getCurrentClippingPath());
}
+
+ /**
+ * Creates a buffered image for a transparency group result.
+ *
+ * @param clippingPath clipping path (in current graphics2D coordinates)
+ * @param resources Global resources
+ * @param content Content of the transparency group to create
+ * @return {@link Group} object
+ */
+ private Group createGroup(GeneralPath clippingPath, PDResources resources, COSStream content) throws IOException {
+ return new Group(clippingPath, resources, content);
+ }
+
+
+ /**
+ * Draws the transparency group into a {@link BufferedImage} object and returns it together with the transformation matrix
+ *
+ * @param context {@link PageDrawer} object
+ * @return PageDrawer.Group
+ * @throws IOException
+ */
+ public PageDrawer.Group createPageDrawerGroup(PDFormXObject form) throws IOException {
+ // save the graphics state
+ saveGraphicsState();
+
+ try {
+ PDResources pdResources = form.getResources();
+ if (pdResources == null) {
+ pdResources = getResources();
+ }
+
+ // if there is an optional form matrix, we have to
+ // map the form space to the user space
+ Matrix matrix = form.getMatrix();
+ if(matrix != null)
+ {
+ Matrix xobjectCTM = matrix.multiply(getGraphicsState().getCurrentTransformationMatrix());
+ getGraphicsState().setCurrentTransformationMatrix(xobjectCTM);
+ }
+
+ PDRectangle bBox = form.getBBox();
+
+ float x1 = bBox.getLowerLeftX();
+ float y1 = bBox.getLowerLeftY();
+ float x2 = bBox.getUpperRightX();
+ float y2 = bBox.getUpperRightY();
+
+ Point2D p0 = transformedPoint(x1, y1);
+ Point2D p1 = transformedPoint(x2, y1);
+ Point2D p2 = transformedPoint(x2, y2);
+ Point2D p3 = transformedPoint(x1, y2);
+
+ GeneralPath path = new GeneralPath();
+ path.moveTo((float) p0.getX(), (float) p0.getY());
+ path.lineTo((float) p1.getX(), (float) p1.getY());
+ path.lineTo((float) p2.getX(), (float) p2.getY());
+ path.lineTo((float) p3.getX(), (float) p3.getY());
+ path.closePath();
+
+ return createGroup(path, pdResources, form.getCOSStream());
+ }
+ finally {
+ // restore the graphics state
+ restoreGraphicsState();
+ }
+
+ }
+
+ /**
+ * Create for rendering transparency groups...
+ *
+ **/
+ public class Group {
+ /**
+ * {@link BufferedImage} object to draw into...
+ */
+ private final BufferedImage mImage;
+ /**
+ * Matrix for drawing the result
+ */
+ private final Matrix mResultMatrix;
+
+
+ private final int minX;
+ private final int minY;
+ private final int width;
+ private final int height;
+
+ /**
+ * Creates a group object. The group can now be created only if the underlying {@link Graphics2D} implementation
+ * is SunGraphics2D (i.e. rendering to bitmap). For all other implementations, this throws
+ * an {@link UnsupportedOperationException}.
+ *
+ * @param image
+ * @param g2d
+ */
+ private Group(GeneralPath clippingPath, PDResources resources, COSStream content) throws IOException {
+ Graphics2D g2dOriginal = graphics;
+
+ // Check underlying g2d
+ double unitSize = 1.0;
+
+ Area resultClippingArea = new Area(getGraphicsState().getCurrentClippingPath());
+ if(clippingPath != null) {
+ Area newArea = new Area(clippingPath);
+ resultClippingArea.intersect(newArea);
+ }
+
+ AffineTransform at = g2dOriginal.getTransform();
+ at.scale(unitSize, unitSize);
+ Shape clippingPathInPixels = at.createTransformedShape(resultClippingArea);
+ Rectangle2D bounds2D = clippingPathInPixels.getBounds2D();
+
+ minX = (int) Math.floor(bounds2D.getMinX());
+ minY = (int) Math.floor(bounds2D.getMinY());
+ int maxX = (int) Math.floor(bounds2D.getMaxX()) + 1;
+ int maxY = (int) Math.floor(bounds2D.getMaxY()) + 1;
+
+ width = maxX - minX;
+ height = maxY - minY;
+ mImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // FIXME - color space
+ Graphics2D groupG2D = mImage.createGraphics();
+ groupG2D.translate(-minX, -minY);
+ groupG2D.transform(at);
+ groupG2D.setClip(resultClippingArea);
+
+ AffineTransform atInv = null;
+ Matrix tmpResultMatrix = null;
+ try {
+ atInv = groupG2D.getTransform().createInverse();
+ atInv.scale(width, -height);
+ atInv.translate(0, -1);
+ tmpResultMatrix = new Matrix();
+ tmpResultMatrix.setFromAffineTransform(atInv);
+ }
+ catch (NoninvertibleTransformException e) {
+ LOG.warn("Non-invertible transform when rendering a transparency group.", e);
+ }
+ mResultMatrix = tmpResultMatrix;
+
+ PDGraphicsState gs = getGraphicsState();
+ gs.setBlendMode(BlendMode.NORMAL);
+ gs.setAlphaConstants(1.0);
+ gs.setNonStrokeAlphaConstants(1.0);
+ gs.setSoftMask(null);
+ graphics = groupG2D;
+ try {
+ processSubStream(resources, content);
+ }
+ finally
+ {
+ graphics = g2dOriginal;
+ }
+ }
+
+ public BufferedImage getImage() {
+ return mImage;
+ }
+
+ /**
+ * @return the resultMatrix
+ */
+ public Matrix getResultMatrix() {
+ return mResultMatrix;
+ }
+
+ public void drawResult() throws IOException {
+ if (mResultMatrix != null) {
+ saveGraphicsState();
+ drawImage(mImage, mResultMatrix.createAffineTransform());
+ restoreGraphicsState();
+ }
+ }
+
+ public Raster getAlphaRaster() {
+ return mImage.getAlphaRaster().createTranslatedChild(minX, minY);
+ }
+
+ public Raster getLuminosityRaster() {
+ BufferedImage tmpImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
+ Graphics g = tmpImage.getGraphics();
+ g.drawImage(mImage, 0, 0, null);
+
+ WritableRaster result = tmpImage.getRaster();
+ return result.createTranslatedChild(minX, minY);
+ }
+ }
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java Tue Jun 17 00:20:17 2014
@@ -610,19 +610,27 @@ public class PDFStreamEngine
}
/**
- * @return Returns the graphicsStack.
+ * Pushes the current graphics state to the stack.
*/
- public Stack<PDGraphicsState> getGraphicsStack()
+ public void saveGraphicsState()
{
- return graphicsStack;
+ graphicsStack.push((PDGraphicsState) getGraphicsState().clone());
}
/**
- * @param value The graphicsStack to set.
+ * Pops the current graphics state from the stack.
*/
- public void setGraphicsStack(Stack<PDGraphicsState> value)
+ public void restoreGraphicsState()
{
- graphicsStack = value;
+ graphicsState = graphicsStack.pop();
+ }
+
+ /**
+ * @return Returns the size of the graphicsStack.
+ */
+ public int getGraphicsStackSize()
+ {
+ return graphicsStack.size();
}
/**
@@ -747,5 +755,4 @@ public class PDFStreamEngine
unsupportedOperators.clear();
}
}
-
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GRestore.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GRestore.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GRestore.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GRestore.java Tue Jun 17 00:20:17 2014
@@ -42,9 +42,9 @@ public class GRestore extends OperatorPr
*/
public void process(PDFOperator operator, List<COSBase> arguments)
{
- if (context.getGraphicsStack().size() > 0)
+ if (context.getGraphicsStackSize() > 0)
{
- context.setGraphicsState( (PDGraphicsState)context.getGraphicsStack().pop() );
+ context.restoreGraphicsState();
}
else
{
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GSave.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GSave.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GSave.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/GSave.java Tue Jun 17 00:20:17 2014
@@ -36,7 +36,7 @@ public class GSave extends OperatorProce
*/
public void process(PDFOperator operator, List<COSBase> arguments)
{
- context.getGraphicsStack().push( (PDGraphicsState)context.getGraphicsState().clone() );
+ context.saveGraphicsState();
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/pagedrawer/Invoke.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/pagedrawer/Invoke.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/pagedrawer/Invoke.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/operator/pagedrawer/Invoke.java Tue Jun 17 00:20:17 2014
@@ -94,27 +94,36 @@ public final class Invoke extends Operat
}
else if (xobject instanceof PDFormXObject)
{
- // save the graphics state
- context.getGraphicsStack().push((PDGraphicsState) context.getGraphicsState().clone());
+ PDFormXObject form = (PDFormXObject) xobject;
+ if ((form.getGroup() != null) && (COSName.TRANSPARENCY.equals(form.getGroup().getSubType()))) {
+ PageDrawer.Group group = drawer.createPageDrawerGroup(form);
- PDFormXObject form = (PDFormXObject) xobject;
- COSStream formContentStream = form.getCOSStream();
+ // Draw the result of the group to the page...
+ group.drawResult();
+ }
+ else
+ {
+ // save the graphics state
+ context.saveGraphicsState();
- // find some optional resources, instead of using the current resources
- PDResources pdResources = form.getResources();
+ COSStream formContentStream = form.getCOSStream();
- // if there is an optional form matrix, we have to map the form space to the user space
- Matrix matrix = form.getMatrix();
- if (matrix != null)
- {
- Matrix xobjectCTM = matrix.multiply(
- context.getGraphicsState().getCurrentTransformationMatrix());
+ // find some optional resources, instead of using the current resources
+ PDResources pdResources = form.getResources();
+
+ // if there is an optional form matrix, we have to map the form space to the user space
+ Matrix matrix = form.getMatrix();
+ if (matrix != null)
+ {
+ Matrix xobjectCTM = matrix.multiply(
+ context.getGraphicsState().getCurrentTransformationMatrix());
context.getGraphicsState().setCurrentTransformationMatrix(xobjectCTM);
- }
- getContext().processSubStream(pdResources, formContentStream);
+ }
+ getContext().processSubStream(pdResources, formContentStream);
- // restore the graphics state
- context.setGraphicsState(context.getGraphicsStack().pop());
+ // restore the graphics state
+ context.restoreGraphicsState();
+ }
}
}
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java Tue Jun 17 00:20:17 2014
@@ -264,7 +264,7 @@ public abstract class ContentStreamEngin
{
if ("q".equals(operator.getOperation()))
{
- int numberOfGraphicStates = this.getGraphicsStack().size();
+ int numberOfGraphicStates = this.getGraphicsStackSize();
if (numberOfGraphicStates > MAX_GRAPHIC_STATES)
{
registerError("Too many graphic states", ERROR_GRAPHIC_TOO_MANY_GRAPHIC_STATES);
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java?rev=1603033&r1=1603032&r2=1603033&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java Tue Jun 17 00:20:17 2014
@@ -141,7 +141,7 @@ public class ContentStreamWrapper extend
this.setGraphicsState(new PDGraphicsState());
this.setTextMatrix(null);
this.setTextLineMatrix(null);
- this.getGraphicsStack().clear();
+ //this.getGraphicsStack().clear();
// this.streamResourcesStack.clear();
}