org.jpedal.render.FXDisplay Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenViewerFX Show documentation
Show all versions of OpenViewerFX Show documentation
An Open Source JavaFX PDF Viewer
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2016 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---------------
* FXDisplay.java
* ---------------
*/
package org.jpedal.render;
import com.idrsolutions.pdf.color.shading.ShadingFactory;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.effect.BlendMode;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.transform.Affine;
import javafx.scene.transform.NonInvertibleTransformException;
import javafx.scene.transform.Transform;
import org.jpedal.color.*;
import org.jpedal.exception.PdfException;
import org.jpedal.fonts.PdfFont;
import org.jpedal.fonts.glyph.PdfGlyph;
import org.jpedal.fonts.tt.TTGlyph;
import org.jpedal.function.FunctionFactory;
import org.jpedal.function.PDFFunction;
import org.jpedal.io.ObjectStore;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.objects.GraphicsState;
import org.jpedal.objects.raw.PatternObject;
import org.jpedal.objects.raw.PdfArrayIterator;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.Matrix;
import org.jpedal.utils.repositories.Vector_Int;
import org.jpedal.utils.repositories.Vector_Object;
import org.jpedal.utils.repositories.generic.Vector_Rectangle_Int;
public class FXDisplay extends GUIDisplay {
private int xx, yy;
final Group pdfContent = new Group();
// private final ObservableList children=pdfContent.getChildren();
private final java.util.List collection=new ArrayList(2000);
public FXDisplay(final int pageNumber, final boolean addBackground, final int defaultSize, final ObjectStore newObjectRef) {
this.rawPageNumber =pageNumber;
this.objectStoreRef = newObjectRef;
this.addBackground=addBackground;
setupArrays(defaultSize);
}
public void setInset(DynamicVectorRenderer currentDisplay, final int x, final int y) {
((FXDisplay)currentDisplay).setInset(x, y);
}
public void setInset(final int x, final int y) {
xx = x;
yy = y;
}
public FXDisplay(final int pageNumber, final ObjectStore newObjectRef, final boolean isPrinting) {
this.rawPageNumber =pageNumber;
this.objectStoreRef = newObjectRef;
this.isPrinting=isPrinting;
setupArrays(defaultSize);
}
/**
* Add output to correct area so we can assemble later.
* Can also be used for any specific code features (ie setting a value)
*/
@Override
public synchronized void writeCustom(final int section, final Object str) {
switch(section){
case FLUSH:
flush();
break;
default:
super.writeCustom(section, str);
}
}
/* remove all page objects and flush queue */
private void flush() {
// children.clear();
pageObjects.clear();
objectType.clear();
areas.clear();
currentItem = 0;
}
/*Method to add Shape, Text or image to main display on page over PDF - will be flushed on redraw*/
@Override
public void drawAdditionalObjectsOverPage(final int[] type, final java.awt.Color[] colors, final Object[] obj) throws PdfException {
if(obj==null){
return ;
}
if(Platform.isFxApplicationThread()){
drawUserContent(type, obj, colors);
}else{
Platform.runLater(new Runnable(){
@Override public void run() {
try {
drawUserContent(type, obj, colors);
} catch (final PdfException e) {
LogWriter.writeLog("Exception with additional objects: " + e.getMessage());
}
}
});
}
}
/* save image in array to draw */
@Override
public int drawImage(final int pageNumber, final BufferedImage image,
final GraphicsState currentGraphicsState,
final boolean alreadyCached, final String name, final int previousUse) {
this.rawPageNumber =pageNumber;
float CTM[][]=currentGraphicsState.CTM;
final WritableImage fxImage = SwingFXUtils.toFXImage(image, null);
final float imageW=(float) fxImage.getWidth();
final float imageH=(float) fxImage.getHeight();
final ImageView im1View = new ImageView(fxImage);
// Stores the affine used on the image to use on the clip later
float[] affine = {CTM[0][0]/imageW,CTM[0][1]/imageW,
-CTM[1][0]/imageH,-CTM[1][1]/imageH,
CTM[2][0]+CTM[1][0],CTM[2][1]+CTM[1][1]};
im1View.getTransforms().setAll(Transform.affine(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]));
setClip(currentGraphicsState, affine, im1View);
setBlendMode(currentGraphicsState, im1View);
addToScene(im1View);
final float WidthModifier = 1;
final float HeightModifier = 1;
//ignore in this case /PDFdata/baseline_screens/customers3/1773_A2.pdf
if(CTM[0][0]>0 && CTM[0][0]<0.05 && CTM[0][1]!=0 && CTM[1][0]!=0 && CTM[1][1]!=0){
areas.addElement(null);
}else{
w=(int)(CTM[0][0]*WidthModifier);
if(w==0) {
w = (int) (CTM[0][1] * WidthModifier);
}
h=(int)(CTM[1][1]*HeightModifier);
if(h==0) {
h = (int) (CTM[1][0] * HeightModifier);
}
//fix negative height on Ghostscript image in printing
final int x1=(int)currentGraphicsState.x;
int y1=(int)currentGraphicsState.y;
final int w1=w;
int h1=h;
if(h1<0){
y1 += h1;
h1=-h1;
}
if(h1==0) {
h1 = 1;
}
final int[] rectParams = {x1,y1,w1,h1};
areas.addElement(rectParams);
objectType.addElement(DynamicVectorRenderer.IMAGE);
}
final boolean cacheInMemory=(image.getWidth()<100 && image.getHeight()<100) || image.getHeight()==1;
if(!cacheInMemory){
pageObjects.addElement(null);
}else {
pageObjects.addElement(image);
}
if(rawKey==null){
objectStoreRef.saveStoredImageAsBytes(pageNumber+"_HIRES_"+currentItem,image,false);
imageIDtoName.put(currentItem,pageNumber+"_HIRES_"+currentItem);
}else{
objectStoreRef.saveStoredImageAsBytes(pageNumber+"_HIRES_"+currentItem+ '_' +rawKey,image,false);
imageIDtoName.put(currentItem,pageNumber+"_HIRES_"+currentItem+ '_' +rawKey);
}
currentItem++;
return currentItem-1;
}
/*save shape in array to draw*/
@Override
public void drawShape(final Object rawShape, final GraphicsState currentGraphicsState) {
final Shape currentShape=(javafx.scene.shape.Shape)rawShape;
final float[] affine = {currentGraphicsState.CTM[0][0], currentGraphicsState.CTM[0][1], currentGraphicsState.CTM[1][0], currentGraphicsState.CTM[1][1], currentGraphicsState.CTM[2][0], currentGraphicsState.CTM[2][1]};
// Fixes Pages from FDB-B737-FRM_nowatermark.pdf
// if((affine[3] < 1 && affine[3] > 0)){
// affine[3] = 1; //
// }
currentShape.getTransforms().add(javafx.scene.transform.Transform.affine(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]));
//if Pattern, convert to Image with Pattern on instead
if(currentGraphicsState.nonstrokeColorSpace.getID()==ColorSpaces.Pattern){
drawPatternedShape(currentGraphicsState, (Path) currentShape);
}else{
setFXParams(currentShape,currentGraphicsState.getFillType(),currentGraphicsState, changeLineArtAndText);
setClip(currentGraphicsState, affine, currentShape);
setBlendMode(currentGraphicsState, currentShape);
addToScene(currentShape);
}
final int[] shapeBounds = {(int)currentShape.getBoundsInLocal().getMinX(), (int)currentShape.getBoundsInLocal().getMinY()
, (int)currentShape.getBoundsInLocal().getWidth(), (int)currentShape.getBoundsInLocal().getHeight()};
pageObjects.addElement(currentShape);
objectType.addElement(DynamicVectorRenderer.SHAPE);
areas.addElement(shapeBounds);
currentItem++;
}
private void drawPatternedShape(final GraphicsState currentGraphicsState, final Path currentShape){
final PatternColorSpace patternCS=(PatternColorSpace)currentGraphicsState.nonstrokeColorSpace;
Bounds bounds = currentShape.getBoundsInParent();
PatternObject patternObj = patternCS.getPatternObj();
final int patternType = patternObj.getInt(PdfDictionary.PatternType);
if (patternType == 1) { //tiling pattern
//get Image as BufferedImage and convert to javafx WritableImage
final BufferedImage imageForPattern = patternCS.getImageForPatternedShape(currentGraphicsState);
if (imageForPattern == null) {
return;
}
Image fxImage = SwingFXUtils.toFXImage(imageForPattern, null);
double iw = fxImage.getWidth();
double ih = fxImage.getHeight();
// final double xPos=currentShape.getBoundsInParent().getMinX();
// final double yPos=currentShape.getBoundsInParent().getMinY();
// double pw = currentShape.getBoundsInLocal().getWidth();
// double ph = currentShape.getBoundsInLocal().getHeight();
ImagePattern pattern = new ImagePattern(fxImage, 0, 0, iw, ih,false);
currentShape.setStroke(new Color(0, 0, 0, 0));
currentShape.setFill(pattern);
} else {
currentShape.setFill(getShadingPaint(patternObj, patternCS, bounds));
}
addToScene(currentShape);
// if(true) return;
// final PatternColorSpace fillCS=(PatternColorSpace)currentGraphicsState.nonstrokeColorSpace;
// //get Image as BufferedImage and convert to javafx WritableImage
// final BufferedImage imageForPattern = fillCS.getImageForPatternedShape(currentShape);
// if(imageForPattern == null) {
// return;
// }
//
// final WritableImage pattern = SwingFXUtils.toFXImage(imageForPattern, null);
// final double xPos=currentShape.getBoundsInParent().getMinX();
// final double yPos=currentShape.getBoundsInParent().getMinY();
//
// final ImageView patternView = new ImageView(pattern);
// patternView.setX(xPos+1);
// patternView.setY(yPos+1);
//addToScene(patternView, currentShape);
}
private static Paint getShadingPaint(PatternObject patternObj, PatternColorSpace patternCS, Bounds bounds) {
final PdfObjectReader currentPdfFile = patternCS.getObjectReader();
final PdfObject shading=patternObj.getDictionary(PdfDictionary.Shading);
final PdfArrayIterator ColorSpace=shading.getMixedArray(PdfDictionary.ColorSpace);
final GenericColorSpace newColorSpace= ColorspaceFactory.getColorSpaceInstance(currentPdfFile, ColorSpace);
float[][] matrix = {{1,0,0},{0,1,0},{0,0,1}};
final float[] inputs=patternObj.getFloatArray(PdfDictionary.Matrix);
if(inputs!=null){
matrix = new float[][]{{inputs[0], inputs[1], 0f}, {inputs[2], inputs[3], 0f}, {inputs[4], inputs[5], 1f}};
}
final int shadingType = shading.getInt(PdfDictionary.ShadingType);
final float[] background = shading.getFloatArray(PdfDictionary.Background);
final PdfObject functionObj = shading.getDictionary(PdfDictionary.Function);
final PdfArrayIterator keys = shading.getMixedArray(PdfDictionary.Function);
PDFFunction [] function = null;
if (functionObj != null) {
function = new PDFFunction[1];
function[0] = FunctionFactory.getFunction(functionObj, currentPdfFile);
} else if (keys != null) {
int functionCount = 0;
if (keys != null) {
functionCount = keys.getTokenCount();
}
if (keys != null) {
final PdfObject[] subFunction = new PdfObject[functionCount];
for (int i = 0; i < functionCount; i++) {
subFunction[i]=ColorspaceFactory.getFunctionObjectFromRefOrDirect(currentPdfFile, keys.getNextValueAsByte(true));
}
function = new PDFFunction[subFunction.length];
for (int i1 = 0, imax = subFunction.length; i1 < imax; i1++) {
function[i1] = FunctionFactory.getFunction(subFunction[i1], currentPdfFile);
}
}
}
if (shadingType == 2) {
return getAxialPaint(newColorSpace, background, shading, matrix, function, bounds);
} else {
return new Color(0, 0, 0, 0);
}
}
private static Paint getAxialPaint(GenericColorSpace shadingColorSpace, float[] background, PdfObject shadingObject, float[][] mm, PDFFunction[] function, Bounds bounds) {
float[] domain = shadingObject.getFloatArray(PdfDictionary.Domain);
if (domain == null) {
domain = new float[]{0.0f, 1.0f};
}
boolean [] extension = shadingObject.getBooleanArray(PdfDictionary.Extend);
if (extension == null) {
extension = new boolean[]{false, false};
}
Color bgColor = new Color(0,0,0,0);
if(background != null){
shadingColorSpace.setColor(background, 4);
shadingColorSpace.getColor();
PdfPaint pp = shadingColorSpace.getColor();
int rgb = pp.getRGB();
bgColor = new Color(((rgb>>16)&0xff)/255.0, ((rgb>>8)&0xff)/255.0, (rgb&0xff)/255.0,1);
}
Color colorE0 = bgColor;
Color colorE1 = bgColor;
float[] coords = shadingObject.getFloatArray(PdfDictionary.Coords);
float x0 = coords[0];
float y0 = coords[1];
float x1 = coords[2];
float y1 = coords[3];
float[] temp = Matrix.transformPoint(mm, x0, y0);
x0 = temp[0];
y0 = temp[1];
temp = Matrix.transformPoint(mm, x1, y1);
x1 = temp[0];
y1 = temp[1];
float t0 = domain[0];
float t1 = domain[1];
Color colorT0 = calculateColor(t0, shadingColorSpace, function);
Color colorT1 = calculateColor(t1, shadingColorSpace, function);
colorE0 = extension[0] ? colorT0 : colorE0;
colorE1 = extension[1] ? colorT1 : colorE1;
Stop[] stops = {new Stop(0,colorE0),new Stop(0.01, colorT0), new Stop(0.99, colorT1), new Stop(1,colorE1)};
// Stop[] stops = new Stop[]{new Stop(0.1, colorT0), new Stop(0.9, colorT1)};
if(1==2){
Matrix.show(mm);
double bx = bounds.getMinX();
double by = bounds.getMinY();
double mx = bounds.getMaxX();
double my = bounds.getMaxY();
System.out.println(bx+by+mx+my);
}
return new LinearGradient(x0, y0, x1, y1, false, CycleMethod.NO_CYCLE, stops);
}
private static Color calculateColor(final float val, GenericColorSpace shadingColorSpace, PDFFunction[] function) {
final float[] colValues = ShadingFactory.applyFunctions(function, new float[]{val});
shadingColorSpace.setColor(colValues, colValues.length);
PdfPaint pp = shadingColorSpace.getColor();
int rgb = pp.getRGB();
return new Color(((rgb>>16)&0xff)/255.0, ((rgb>>8)&0xff)/255.0, (rgb&0xff)/255.0,1);
}
protected void setFXParams(final Shape currentShape, final int fillType, final GraphicsState currentGraphicsState, boolean allowColorChange){
// Removes the default black stroke on shapes
currentShape.setStroke(null);
if (fillType == GraphicsState.FILL || fillType == GraphicsState.FILLSTROKE) {
//get fill colour
int fillCol=currentGraphicsState.nonstrokeColorSpace.getColor().getRGB();
if (allowColorChange) {
//If we have an alt text color, its within threshold and not an additional item, use alt color
if (textColor != null && (itemToRender == -1 || (endItem == -1 || itemToRender <= endItem)) && checkColorThreshold(fillCol)) {
fillCol = textColor.getRGB();
}
}
//get value as rgb and set current colour used in fill
final int r = ((fillCol >> 16) & 255); //red
final int g = ((fillCol >> 8) & 255); //green
final int b = ((fillCol) & 255); //blue
final double a=currentGraphicsState.getAlpha(GraphicsState.FILL); //alpha
currentShape.setFill(javafx.scene.paint.Color.rgb(r,g,b,a));
}
if (fillType == GraphicsState.STROKE) {
//get fill colour
int strokeCol=currentGraphicsState.strokeColorSpace.getColor().getRGB();
if (allowColorChange) {
//If we have an alt text color, its within threshold and not an additional item, use alt color
if (textColor != null && (itemToRender == -1 || (endItem == -1 || itemToRender <= endItem)) && checkColorThreshold(strokeCol)) {
strokeCol = textColor.getRGB();
}
}
//get value as rgb and set current colour used in fill
final int r = ((strokeCol >> 16) & 255); //red
final int g = ((strokeCol >> 8) & 255); //green
final int b = ((strokeCol) & 255); //blue
final double a=currentGraphicsState.getAlpha(GraphicsState.STROKE); //alpha
currentShape.setStroke(javafx.scene.paint.Color.rgb(r,g,b,a));
currentGraphicsState.applyFXStroke(currentShape);
}
}
@Override
public void drawCustom(final Object value) {
addToScene((Node) value);
}
/**
* store glyph info
* @param Trm the Trm matrix (x,y is Trm[2][0], Trm[2][1]), other values are width (usually Trm[0][0] unless
* rotated when could be Trm[0][1]) and height (usually Trm[1][1] or sometimes Trm[1][0]) Trm is defined in PDF
* specification
* @param fontSize The font size of the drawn text
* @param embeddedGlyph For displaying rendered test
* @param javaGlyph Is of type object used to draw text
* @param type The type of text rendering
* @param gs The graphics state to use
* @param textScaling An array of text scaling
* @param glyf Is of type String used to draw text in the Viewer
* @param currentFontData font of the current decoded page in the Viewer
* @param glyfWidth The width of drawn text
*/
@Override
public void drawEmbeddedText(final float[][] Trm, final int fontSize, final PdfGlyph embeddedGlyph,
final Object javaGlyph, final int type, final GraphicsState gs, final double[] textScaling, final String glyf, final PdfFont currentFontData, final float glyfWidth) {
//lock out type3
if(type==DynamicVectorRenderer.TYPE3) {
return;
}
//case one - text is using Java to draw it
if(embeddedGlyph == null && javaGlyph == null){
final Text t = new Text(glyf);
// Get the affine
/*
* Set the font for the current decoded page in the Viewer
*/
final Font f = Font.font(currentFontData.getGlyphData().font_family_name, fontSize);
t.setFont(f);
/*
* Set the text color (fill and stroke)
*/
setFXParams(t, GraphicsState.FILL, gs, textColor!=null);
// If the stroke is needed, fill it in
if((gs.getTextRenderType() & GraphicsState.STROKE) == GraphicsState.STROKE ){
setFXParams(t, GraphicsState.STROKE, gs, textColor!=null);
}
setBlendMode(gs, t);
// Set the affines
if(type!=DynamicVectorRenderer.TRUETYPE){
final double r=1d / fontSize;
t.getTransforms().add(Transform.affine(textScaling[0]*r,textScaling[1]*r,textScaling[2]*r,textScaling[3]*r,Trm[2][0],Trm[2][1]));
}else{
final double r=1d / fontSize;
t.getTransforms().setAll(Transform.affine(Trm[0][0]*r,Trm[0][1]*r,Trm[1][0]*r,Trm[1][1]*r,Trm[2][0],Trm[2][1]));
}
final float[] transform= {Trm[0][0],Trm[1][0],Trm[0][1],Trm[1][1],Trm[2][0],Trm[2][1]};
final Shape clip = gs.getFXClippingShape();
if(clip!=null && !clip.contains(Trm[2][0],Trm[2][1])){
setClip(gs, transform, t);
}
pageObjects.addElement(t);
addToScene(t);
}else { //case two - text is using our font engine
// System.out.println("embeddedGlyph = "+ embeddedGlyph+" "+at+" "+Trm[0][0]);
final Path path=(Path) embeddedGlyph.getPath();
if(path==null){
if(LogWriter.isRunningFromIDE){
System.out.println("Null FX path in "+embeddedGlyph);
}
return;
}
path.setFillRule(FillRule.EVEN_ODD);
if(type!=DynamicVectorRenderer.TRUETYPE){
path.getTransforms().setAll(Transform.affine(textScaling[0],textScaling[1],textScaling[2],textScaling[3],textScaling[4],textScaling[5]));
}else{
final double r=1d/100d;
if(!TTGlyph.useHinting) {
path.getTransforms().setAll(Transform.affine(textScaling[0], textScaling[1], textScaling[2], textScaling[3], textScaling[4], textScaling[5]));
} else {
path.getTransforms().setAll(Transform.affine(textScaling[0] * r, textScaling[1] * r, textScaling[2] * r, textScaling[3] * r, textScaling[4], textScaling[5]));
}
}
setFXParams(path,gs.getTextRenderType(),gs, textColor!=null);
setBlendMode(gs, path);
final float[] transform= {Trm[0][0],Trm[1][0],Trm[0][1],Trm[1][1],Trm[2][0],Trm[2][1]};
final Shape clip = gs.getFXClippingShape();
if(clip!=null && !clip.contains(Trm[2][0],Trm[2][1])){
setClip(gs, transform, path);
}
pageObjects.addElement(path);
addToScene(path);
}
objectType.addElement(type);
if(type<0){
areas.addElement(null);
}else{
if(javaGlyph!=null){
final int[] rectParams = {(int)(Trm[2][0]),(int)Trm[2][1],fontSize,fontSize};
areas.addElement(rectParams);
}else{
/*now text*/
int realSize=fontSize;
if(realSize<0) {
realSize = -realSize;
}
final int[] area= {(int)(Trm[2][0]),(int)Trm[2][1],realSize,realSize};
areas.addElement(area);
}
}
currentItem++;
}
/**
* When Transform.affine() is applied to the image, it's applied to the clip as well.
* This causes the clip to be transformed into the incorrect position.
*
* This code essentially un-transforms the clip so it clips correctly again.
*/
private static void setClip(final GraphicsState currentGraphicsState, final float[] affine, final Node baseNode){
final Shape clip = currentGraphicsState.getFXClippingShape();
if(clip != null){
try {
// Lock out specific matrices from being reversed
if(!Arrays.equals(affine, new float[]{1,0,0,-1,0,0})){
// Side note: initialising a straight up Affine uses the doubles in a different order
final Affine inverseAff = Transform.affine(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]).createInverse();
clip.getTransforms().add(inverseAff);
}
/*
*
* PDFdata\test_data\Hand_Test\awjune2003.pdf and
* PDFdata\test_data\Hand_Test\rechnung_file.PDF
* PDFdata\test_data\Hand_Test\jj.PDF
* PDFdata\test_data\sample_pdfs\CIDs\Article7.pdf
* */
//remove hacky fix with clip to make 23700 work correctly
// boolean applyClip = clip.getBoundsInLocal().getMinX()>baseNode.getBoundsInLocal().getMinX() &&
// baseNode.getBoundsInLocal().getMaxY() > clip.getBoundsInLocal().getMaxY();
//
// if (applyClip) {
baseNode.setClip(clip);
// }
} catch (final NonInvertibleTransformException ex) {
ex.printStackTrace();
}
}
}
public Group getFXPane() {
// System.out.println("getFXPane "+this);
if(collection!=null && !collection.isEmpty()){
// pdfContent.getChildren().removeAll(collection);
pdfContent.getChildren().addAll(collection);
collection.clear();
}
return pdfContent;
}
protected static void setBlendMode(final GraphicsState gs, final Node n){
switch(gs.getBMValue()){
case PdfDictionary.Multiply:
n.setBlendMode(BlendMode.MULTIPLY);
break;
case PdfDictionary.Screen:
n.setBlendMode(BlendMode.SCREEN);
break;
case PdfDictionary.Overlay:
n.setBlendMode(BlendMode.OVERLAY);
break;
case PdfDictionary.Darken:
n.setBlendMode(BlendMode.DARKEN);
break;
case PdfDictionary.Lighten:
n.setBlendMode(BlendMode.LIGHTEN);
break;
case PdfDictionary.ColorDodge:
n.setBlendMode(BlendMode.COLOR_DODGE);
break;
case PdfDictionary.ColorBurn:
n.setBlendMode(BlendMode.COLOR_BURN);
break;
case PdfDictionary.HardLight:
n.setBlendMode(BlendMode.HARD_LIGHT);
break;
case PdfDictionary.SoftLight:
n.setBlendMode(BlendMode.SOFT_LIGHT);
break;
case PdfDictionary.Difference:
n.setBlendMode(BlendMode.DIFFERENCE);
break;
case PdfDictionary.Exclusion:
n.setBlendMode(BlendMode.EXCLUSION);
break;
default:
n.setBlendMode(null);
break;
}
}
/**
* Adds items to scene, ensuring we are on the FX thread
* @param items All the nodes that are added to the Scene
*/
private void addToScene(final Node items){
collection.add(items);
}
/**
*
* @param defaultSize The size of the array
*/
private void setupArrays(final int defaultSize){
areas=new Vector_Rectangle_Int(defaultSize);
objectType=new Vector_Int(defaultSize);
pageObjects=new Vector_Object(defaultSize);
currentItem = 0;
}
@Override
public void paintBackground(final java.awt.Shape dirtyRegion) {
if (addBackground) {
Path background = new Path();
background.getElements().add(new MoveTo(xx, yy));
background.getElements().add(new LineTo(xx, yy+(int) (h * scaling)));
background.getElements().add(new LineTo(xx+ (int) (w * scaling), yy+(int) (h * scaling)));
background.getElements().add(new LineTo(xx+ (int) (w * scaling), yy));
background.getElements().add(new LineTo(xx, yy));
background.setFill(new Color(backgroundColor.getRed()/255.0f, backgroundColor.getGreen()/255.0f, backgroundColor.getBlue()/255.0f, 1.0f));
addToScene(background);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy