org.jpedal.render.FXDisplay Maven / Gradle / Ivy
/*
* ===========================================
* 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-2017 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
@LICENSE@
*
* ---------------
* 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.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(final 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;
final 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
final 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;
final Bounds bounds = currentShape.getBoundsInParent();
final 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;
}
final Image fxImage = SwingFXUtils.toFXImage(imageForPattern, null);
final double iw = fxImage.getWidth();
final 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();
final 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(final PatternObject patternObj, final PatternColorSpace patternCS, final 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(final GenericColorSpace shadingColorSpace, final float[] background, final PdfObject shadingObject, final float[][] mm, final PDFFunction[] function, final 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();
final PdfPaint pp = shadingColorSpace.getColor();
final 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;
final 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];
final float t0 = domain[0];
final float t1 = domain[1];
final Color colorT0 = calculateColor(t0, shadingColorSpace, function);
final Color colorT1 = calculateColor(t1, shadingColorSpace, function);
colorE0 = extension[0] ? colorT0 : colorE0;
colorE1 = extension[1] ? colorT1 : colorE1;
final 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);
final double bx = bounds.getMinX();
final double by = bounds.getMinY();
final double mx = bounds.getMaxX();
final 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, final GenericColorSpace shadingColorSpace, final PDFFunction[] function) {
final float[] colValues = ShadingFactory.applyFunctions(function, new float[]{val});
shadingColorSpace.setColor(colValues, colValues.length);
final PdfPaint pp = shadingColorSpace.getColor();
final 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, final 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 (!embeddedGlyph.hasHinting()) {
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) {
final 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);
}
}
}