org.jpedal.objects.acroforms.SwingData 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
Open Source (LGPL) JavaFX PDF Viewer for NetBeans plugin
/*
* ===========================================
* 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@
*
* ---------------
* SwingData.java
* ---------------
*/
package org.jpedal.objects.acroforms;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.text.JTextComponent;
import org.jpedal.display.Display;
import org.jpedal.external.CustomFormPrint;
import org.jpedal.objects.acroforms.creation.AnnotationFactory;
import org.jpedal.objects.acroforms.creation.FormFactory;
import org.jpedal.objects.acroforms.creation.JPedalBorderFactory;
import org.jpedal.objects.acroforms.overridingImplementations.CustomImageIcon;
import org.jpedal.objects.acroforms.overridingImplementations.FixImageIcon;
import org.jpedal.objects.acroforms.overridingImplementations.ReadOnlyTextIcon;
import org.jpedal.objects.raw.FormObject;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.utils.LogWriter;
/**
* Swing specific implementation of Widget data
* (all non-Swing variables defined in ComponentData)
*/
public class SwingData extends GUIData {
//used to enable work around for bug in JDK1.6.0_10+
//NEEDS to be public
public static boolean JVMBugRightAlignFix;
CustomFormPrint customFormPrint;
JFrame dummyPanel;
boolean g2SwingRenderComplete;
//panel components attached to
private JPanel panel;
//scaling used for readOnly text icons drawn as images
public static int readOnlyScaling = -1;
public SwingData() {
}
@Override
public void dispose() {
super.dispose();
if (dummyPanel != null) {
if (SwingUtilities.isEventDispatchThread()) {
dummyPanel.dispose();
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
dummyPanel.dispose();
}
});
} catch (final InvocationTargetException e) {
e.printStackTrace();
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* render component onto G2 for print of image creation
*
* @param printcombo = tells us to print the raw combobox, and dont do aymore formatting of the combobox, should only be called from this method.
*/
private void renderComponent(final Graphics2D g2, final FormObject formObject, final Component comp, final int rotation, boolean printcombo, final int indent, final boolean isPrinting) {
if (comp != null) {
boolean editable = false;
final int page = formObject.getPageNumber();
if (!printcombo && comp instanceof JComboBox) {
//if we have the comobobox, adapt so we see what we want to
//for the combobox we need to print the first item within it otherwise we doent see the contents.
final JComboBox combo = (JComboBox) comp;
if (combo.isEditable()) {
editable = true;
combo.setEditable(false);
}
if (combo.getComponentCount() > 0) {
final Object selected = combo.getSelectedItem();
if (selected != null) {
final JTextField text = new JTextField();
text.setText(selected.toString());
text.setBackground(combo.getBackground());
text.setForeground(combo.getForeground());
text.setFont(combo.getFont());
text.setBorder(combo.getBorder());
renderComponent(g2, formObject, text, rotation, false, indent, isPrinting);
}
}
//set flag to say this is the combobox.
//(we dont want to print this, as we have printed it as a textfield )
printcombo = true;
}
if (!printcombo) {
final AffineTransform ax = g2.getTransform();
//when true works on printing,
//whnen false works for testrenderer, on most except eva_subjob_quer.pdf
if (isPrinting) {
//if we dont have the combobox print it
scaleComponent(formObject, 1, rotation, comp, false, indent, isPrinting);
//work out new translate after rotate deduced from FixImageIcon
final AffineTransform at;
switch (360 - rotation) {
case 270:
at = AffineTransform.getRotateInstance(
(270 * java.lang.Math.PI) / 180, 0, 0);
g2.translate(comp.getBounds().y + cropOtherY[page] - insetH,
pageData.getCropBoxHeight(page) - comp.getBounds().x + insetW);
g2.transform(at);
g2.translate(-insetW, 0);
break;
case 90:
at = AffineTransform.getRotateInstance(
(90 * java.lang.Math.PI) / 180, 0, 0);
g2.translate(comp.getBounds().y + cropOtherY[page] - insetH,
comp.getBounds().x + insetW);
g2.transform(at);
g2.translate(0, -insetH);
break;
case 180://not tested
at = AffineTransform.getRotateInstance(
(180 * java.lang.Math.PI) / 180, 0, 0);
//translate to x,y of comp before applying rotate.
g2.translate(comp.getBounds().x - insetW, comp.getBounds().y + cropOtherY[page]);
g2.transform(at);
g2.translate(-insetW, -insetH); //will prob need this to work
break;
default:
//translate to x,y of comp before applying rotate.
g2.translate(comp.getBounds().x - insetW, comp.getBounds().y + cropOtherY[page]);
break;
}
} else { //used for testrenderer, images
//if we dont have the combobox print it
scaleComponent(formObject, 1, rotation, comp, false, indent, isPrinting);
Rectangle rect = comp.getBounds();
//translate to x,y of comp before applying rotate.
g2.translate(rect.x - insetW, rect.y + cropOtherY[page]);
//only look at rotate on text fields as other fields should be handled.
if (comp instanceof JTextComponent) {
if (pageData.getRotation(page) == 90 || pageData.getRotation(page) == 270) {
comp.setBounds(rect.x, rect.y, rect.height, rect.width);
rect = comp.getBounds();
}
//fix for file eva_subjob_quer.pdf as it has page rotations 90 0 90 0, which makes
//page 1 and 3 print wrong when using each pages rotation value.
int rotate = rotation - pageData.getRotation(0);
if (rotate < 0) {
rotate = 360 + rotate;
}
//work out new translate after rotate deduced from FixImageIcon
final AffineTransform at;
switch (rotate) {
case 270:
at = AffineTransform.getRotateInstance(
(rotate * java.lang.Math.PI) / 180, 0, 0);
g2.transform(at);
g2.translate(-rect.width, 0);
break;
case 90://not tested
at = AffineTransform.getRotateInstance(
(rotate * java.lang.Math.PI) / 180, 0, 0);
g2.transform(at);
g2.translate(0, -rect.height);
break;
case 180://not tested
at = AffineTransform.getRotateInstance(
(rotate * java.lang.Math.PI) / 180, 0, 0);
g2.transform(at);
g2.translate(-rect.width, -rect.height);
break;
}
}
}
//fix for bug in Java 1.6.0_10 onwards with right aligned values
boolean isPainted = false;
//hack for a very sepcific issue so rather leave
//Rog's code intack and take out for ME
if (JVMBugRightAlignFix && comp instanceof JTextField) {
final JTextField field = new JTextField();
final JTextField source = (JTextField) comp;
if (source.getHorizontalAlignment() == JTextField.RIGHT) {
field.setFont(source.getFont());
field.setLocation(source.getLocation());
field.setSize(source.getSize());
field.setBorder(source.getBorder());
field.setHorizontalAlignment(JTextField.RIGHT);
//Rog's modified code
int additionalBlanks = 0;
int width = g2.getFontMetrics(comp.getFont()).stringWidth(new
String(createCharArray(' ', maxLengthForTextOnPage -
source.getText().length())) + source.getText());
final int eightPointWidth =
g2.getFontMetrics(comp.getFont().deriveFont(7.0F)).stringWidth(new
String(createCharArray(' ', maxLengthForTextOnPage -
source.getText().length())) + source.getText());
final int difference = width - eightPointWidth;
if (difference > 0) {
additionalBlanks = difference /
g2.getFontMetrics(comp.getFont().deriveFont(7.0F)).stringWidth(" ");
}
final String originalTest = source.getText();
int bunchOfSpaces = (maxLengthForTextOnPage +
additionalBlanks) - source.getText().length();
field.setText(new String(createCharArray(' ',
bunchOfSpaces)) + originalTest);
width =
g2.getFontMetrics(comp.getFont()).stringWidth(field.getText());
int insets = 0;
if (field.getBorder() != null) {
insets = (field.getBorder().getBorderInsets(field).left + field.getBorder().getBorderInsets(field).right);
}
boolean needsChange = false;
String newText;
while (bunchOfSpaces > 0 && width > field.getWidth() - insets) {
bunchOfSpaces = (maxLengthForTextOnPage + additionalBlanks) - source.getText().length();
newText = new String(createCharArray(' ', bunchOfSpaces)) + originalTest;
field.setText(newText);
additionalBlanks--;
width = g2.getFontMetrics(comp.getFont().deriveFont(7.0F)).stringWidth(field.getText());
needsChange = true;
}
if (needsChange) {
additionalBlanks--;
bunchOfSpaces = (maxLengthForTextOnPage + additionalBlanks) - source.getText().length();
newText = new String(createCharArray(' ', bunchOfSpaces)) + originalTest;
field.setText(newText);
}
field.paint(g2);
isPainted = true;
}
}
if (!isPainted) {
if (SwingUtilities.isEventDispatchThread()) {
comp.paint(g2);
} else {
g2SwingRenderComplete = false;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
comp.paint(g2);
g2SwingRenderComplete = true;
}
});
while (!g2SwingRenderComplete) {
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
LogWriter.writeLog("Exception " + e.getMessage());
}
}
g2SwingRenderComplete = false;
}
}
//We need to set the popup back to the correct size otherwise they will be incorrectly sized
if (isPrinting && comp instanceof JInternalFrame) {
scaleComponent(formObject, displayScaling, rotation, comp, false, indent, false);
}
g2.setTransform(ax);
}
if (editable) {
((JComboBox) comp).setEditable(true);
}
}
}
/**
* render component onto G2 for print of image creation
*/
private void renderComponent(final Graphics2D g2, final FormObject formObject, final boolean isPrinting) {
final int page = formObject.getPageNumber();
final AffineTransform ax = g2.getTransform();
final Font backup = g2.getFont();
final Stroke st = g2.getStroke();
final Color old = g2.getColor();
final Shape oldClip = g2.getClip();
final Composite oldCom = g2.getComposite();
//Translate to correct y coord for crop box
g2.translate(0, pageData.getMediaBoxHeight(page) - pageData.getCropBoxHeight(page));
if (formObject.getParameterConstant(PdfDictionary.Subtype) == PdfDictionary.Text) {
final String name = formObject.getName(PdfDictionary.Name);
if (name != null && name.equals("Comment")) {
/* Name of the icon image to use for the icon of this annotation
* - predefined icons are needed for names:-
* Comment, Key, Note, Help, NewParagraph, Paragraph, Insert
*/
try {
final BufferedImage commentIcon = ImageIO.read(getClass().getResource("/org/jpedal/objects/acroforms/res/comment.png"));
g2.drawImage(commentIcon, formObject.getBoundingRectangle().x, pageData.getCropBoxHeight(page) - formObject.getBoundingRectangle().y, formObject.getBoundingRectangle().width, formObject.getBoundingRectangle().height, null);
} catch (final Exception e) {
LogWriter.writeLog("Exception: " + e.getMessage());
}
}
if (formObject.getFloatArray(PdfDictionary.C) == null) {
formObject.setFloatArray(PdfDictionary.C, new float[]{1.0f, 1.0f, 0.0f});
}
}
final float[] col = formObject.getFloatArray(PdfDictionary.C);
Color bgColor = null;
if (col != null) {
if (col[0] > 1 || col[1] > 1 || col[2] > 1) {
bgColor = new Color((int) col[0], (int) col[1], (int) col[2]);
} else {
bgColor = new Color(col[0], col[1], col[2]);
}
}
if (formObject.getParameterConstant(PdfDictionary.Subtype) == PdfDictionary.Popup
&& formObject.getBoolean(PdfDictionary.Open)) {
FormRenderUtilsG2.renderPopupWindow(g2, formObject, bgColor, isPrinting, pageData.getCropBoxHeight(page));
}
//Revert back font before continuing
g2.setFont(backup);
if (AcroRenderer.isAnnotation(formObject) && formObject.getParameterConstant(PdfDictionary.Subtype) != PdfDictionary.Widget) {
final BufferedImage bi = AnnotationFactory.getIcon(formObject);
g2.drawImage(bi, formObject.getBoundingRectangle().x, pageData.getCropBoxHeight(page) - (formObject.getBoundingRectangle().y + formObject.getBoundingRectangle().height), null);
} else {
/*
* Type must be Border W width in points (if 0 no border, default =1) S
* style - (default =S) S=solid, D=dashed (pattern specified by D entry
* below), B=beveled(embossed appears to above page), I=inset(engraved
* appeared to be below page), U=underline ( single line at bottom of
* boundingbox) D array phase - e.g. [a b] c means:- a=on blocks,b=off
* blocks(if not present default to a), c=start of off block preseded
* index is on block. i.e. [4] 6 :- 4blocks on 4blocks off, block[6] if
* off - 1=off 2=on 3=on 4=on 5=on 6=off 7=off 8=off 9=off etc...
*
*/
final int borderWidth = FormRenderUtilsG2.renderBorder(g2, formObject, pageData.getCropBoxHeight(page));
//Revert back stroke before continuing
g2.setStroke(st);
final String textValue = formObject.getValue();
if (textValue != null) {
final FontMetrics metrics = FormRenderUtilsG2.renderFont(g2, formObject, textValue, borderWidth);
//Text is drawn from the baseline so inorder to draw the highlights
//correctly we need to add te fonts decent
int justification = formObject.getAlignment();
final Rectangle2D r = metrics.getStringBounds(textValue, g2);
//Always center button output
if (formObject.getFieldFlags()[FormObject.PUSHBUTTON_ID]) {
justification = 0;
}
if (formObject.getObjectArray(PdfDictionary.Opt) != null && !formObject.getFieldFlags()[FormObject.COMBO_ID]) {
FormRenderUtilsG2.renderComboForms(g2, formObject, metrics, r, borderWidth, justification, pageData.getCropBoxHeight(page));
} else {
if (!textValue.isEmpty()) {
g2.setClip(new Rectangle(formObject.getBoundingRectangle().x + borderWidth - 1,
pageData.getCropBoxHeight(page) - (formObject.getBoundingRectangle().y + formObject.getBoundingRectangle().height) + borderWidth - 1,
formObject.getBoundingRectangle().width - (borderWidth * 2) + 2,
formObject.getBoundingRectangle().height - (borderWidth * 2) + 2));
if (formObject.getFieldFlags()[FormObject.MULTILINE_ID]) {
FormRenderUtilsG2.renderMultilineTextField(g2, formObject, metrics, r, textValue, borderWidth, justification, pageData.getCropBoxHeight(page));
} else { //Single Line Field
FormRenderUtilsG2.renderSingleLineTextField(g2, formObject, metrics, r, textValue, borderWidth, justification, pageData.getCropBoxHeight(page));
}
}
}
}
FormRenderUtilsG2.renderQuadPoint(g2, formObject, bgColor, pageData.getCropBoxHeight(page));
}
g2.setTransform(ax);
g2.setFont(backup);
g2.setStroke(st);
g2.setColor(old);
g2.setClip(oldClip);
g2.setComposite(oldCom);
}
/**
* used by fix above
*
* @param c
* @param count
* @return
*/
private static char[] createCharArray(final char c, final int count) {
if (count <= 0) {
return new char[0];
}
final char[] result = new char[count];
Arrays.fill(result, 0, result.length, c);
return result;
}
int maxLengthForTextOnPage;
/**
* draw the forms onto display for print of image. Note different routine to
* handle forms also displayed at present
*/
@Override
public void renderFormsOntoG2(final Object raw, final int pageIndex, final int currentIndent,
final int currentRotation, final Map componentsToIgnore, final FormFactory formFactory, final int pageHeight) {
if (formsUnordered == null || rasterizeForms) {
} else if (this.formFactory.getType() == FormFactory.HTML || this.formFactory.getType() == FormFactory.SVG) {
renderFormsOntoG2WithHTML(pageIndex, componentsToIgnore);
} else if (GraphicsEnvironment.isHeadless() || formFactory == null) ///mark - make 1==1 to enable
{
renderFormsOntoG2InHeadless(raw, pageIndex, componentsToIgnore, formFactory);
} else {
renderFormsOntoG2WithSwing(raw, pageIndex, currentIndent, currentRotation, componentsToIgnore, formFactory, pageHeight);
}
}
/**
* Draw forms without swing
*/
@Override
public void renderFormsOntoG2InHeadless(final Object raw, final int pageIndex, final Map componentsToIgnore, final FormFactory formFactory) {
if (formsOrdered == null || formsOrdered[pageIndex] == null) {
return;
}
this.componentsToIgnore = componentsToIgnore;
FormObject formObject;
//only passed in on print so also used as flag
final boolean isPrinting = formFactory != null;
final Graphics2D g2 = (Graphics2D) raw;
final AffineTransform defaultAf = g2.getTransform();
// setup scaling
final AffineTransform aff = g2.getTransform();
aff.scale(1, 1);
g2.setTransform(aff);
//get unsorted components and iterate over forms
for (final FormObject nextVal : formsOrdered[pageIndex]) {
if (nextVal != null) {
formObject = nextVal;
//is this form allowed to be printed
final boolean[] flags = formObject.getCharacteristics();
if (((flags[1] || (isPrinting && !flags[2])))) { //1 hidden, 2 print (hense !)
continue;
}
renderComponent(g2, formObject, isPrinting);
}
}
g2.setTransform(defaultAf);
}
/**
* use Swing to draw forms
*/
private void renderFormsOntoG2WithSwing(final Object raw, final int pageIndex, final int currentIndent, final int currentRotation, final Map componentsToIgnore, final FormFactory formFactory, final int pageHeight) {
this.componentsToIgnore = componentsToIgnore;
Component comp;
FormObject formObject;
//only passed in on print so also used as flag
final boolean isPrinting = formFactory != null;
//fix for issue with display of items in 1.6.0_10+
if (JVMBugRightAlignFix && isPrinting) {
maxLengthForTextOnPage = 0;
//get unsorted components and iterate over forms
for (final FormObject o : formsOrdered[pageIndex]) {
if (o != null) {
formObject = o;
comp = (Component) checkGUIObjectResolved(formObject);
if (comp instanceof JTextField) {
final JTextField text = (JTextField) comp;
final int newLength = text.getText().length();
if (newLength > maxLengthForTextOnPage && text.getHorizontalAlignment() == JTextField.RIGHT) {
maxLengthForTextOnPage = newLength;
}
}
}
}
}
final Graphics2D g2 = (Graphics2D) raw;
final AffineTransform defaultAf = g2.getTransform();
// setup scaling
final AffineTransform aff = g2.getTransform();
aff.scale(1, -1);
aff.translate(0, -pageHeight - insetH);
g2.setTransform(aff);
if (dummyPanel == null) {
dummyPanel = new JFrame();
dummyPanel.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
dummyPanel.pack();
}
//get unsorted components and iterate over forms
for (final FormObject nextVal : formsOrdered[pageIndex]) {
if (nextVal != null) {
formObject = nextVal;
//is this form allowed to be printed
final boolean[] flags = formObject.getCharacteristics();
if (((flags[1] || (isPrinting && !flags[2])))) { //1 hidden, 2 print (hense !)
continue;
}
checkGUIObjectResolved(formObject);
comp = (Component) formObject.getGUIComponent();
if (comp != null && comp.isVisible()) {
final Rectangle bounds = formObject.getBoundingRectangle();
final float boundHeight = bounds.height;
final int swingHeight = comp.getPreferredSize().height + 6;
if (this.componentsToIgnore != null &&
(this.componentsToIgnore.containsKey(formObject.getParameterConstant(PdfDictionary.Subtype)) ||
this.componentsToIgnore.containsKey(formObject.getParameterConstant(PdfDictionary.Type)))) {
} else if (comp instanceof JList && ((JList) comp).getSelectedIndex() != -1 && boundHeight < swingHeight) {
final JList comp2 = (JList) comp;
dummyPanel.add(comp);
final ListModel model = comp2.getModel();
final Object[] array = new Object[model.getSize()];
final int selectedIndex = comp2.getSelectedIndex();
int c = 0;
array[c++] = model.getElementAt(selectedIndex);
for (int i = 0; i < array.length; i++) {
if (i != selectedIndex) {
array[c++] = model.getElementAt(i);
}
}
comp2.setListData(array);
comp2.setSelectedIndex(0);
renderComponent(g2, formObject, comp2, currentRotation, false, currentIndent, isPrinting);
dummyPanel.remove(comp2);
} else {
boolean customPrintoverRide = false;
if (customFormPrint != null) {
//setup scalings
scaleComponent(formObject, 1, rotation, comp, false, indent, isPrinting);
customPrintoverRide = customFormPrint.print(g2, formObject, this);
}
if (!customPrintoverRide) {
//this is where the cust1/display_error file line went, but it affects costena printing.
if (comp instanceof AbstractButton) {
final Object obj = ((AbstractButton) comp).getIcon();
if (obj != null) {
if (obj instanceof FixImageIcon) {
((FixImageIcon) (obj)).setPrinting(true, 1);
} else if (readOnlyScaling > 0 && obj instanceof ReadOnlyTextIcon) {
((ReadOnlyTextIcon) (obj)).setPrinting(true, readOnlyScaling);
}
}
}
dummyPanel.add(comp);
renderComponent(g2, formObject, comp, currentRotation, false, currentIndent, isPrinting);
dummyPanel.remove(comp);
if (comp instanceof AbstractButton) {
final Object obj = ((AbstractButton) comp).getIcon();
if (obj instanceof FixImageIcon) {
((FixImageIcon) (obj)).setPrinting(false, 1);
} else if (obj instanceof ReadOnlyTextIcon) {
((ReadOnlyTextIcon) (obj)).setPrinting(false, 1);
}
}
}
}
}
}
}
g2.setTransform(defaultAf);
// put componenents back
if (currentPage == pageIndex && panel != null) {
resetScaledLocation(displayScaling, rotation, indent);
}
}
/**
* use Swing to draw forms
*/
private void renderFormsOntoG2WithHTML(final int pageIndex, final Map componentsToIgnore) {
this.componentsToIgnore = componentsToIgnore;
FormObject formObject;
//get unsorted components and iterate over forms
for (final FormObject nextVal : formsOrdered[pageIndex]) {
if (nextVal != null) {
formObject = nextVal;
checkGUIObjectResolved(formObject);
}
}
}
/**
* alter font and size to match scaling. Note we pass in compoent so we can
* have multiple copies (needed if printing page displayed).
*/
private void scaleComponent(final FormObject formObject, final float scale, final int rotate, final Component curComp, final boolean redraw, int indent, final boolean isPrinting) {
if (curComp == null || formObject.getPageNumber() == -1) {
return;
}
final int curPage = formObject.getPageNumber();
//work out if visible in Layer
if (layers != null) {
final String layerName = formObject.getLayerName();
if (layerName != null && layers.isLayerName(layerName)) {
final boolean isVisible = layers.isVisible(layerName);
curComp.setVisible(isVisible);
}
}
final int[] bounds;
if (formObject.getParameterConstant(PdfDictionary.Subtype) == PdfDictionary.Popup && !isPrinting) {
bounds = cropComponent(formObject, scale, rotate, redraw, true);
} else {
bounds = cropComponent(formObject, scale, rotate, redraw, false);
}
//rescale the font size
final Font resetFont = curComp.getFont();
if (resetFont != null) {
//send in scale, rotation, and curComp as they could be from the print routines,
//which define these parameters.
//FreeText is a special case so handle here
if (formObject.getParameterConstant(PdfDictionary.Subtype) == PdfDictionary.FreeText) {
final byte[] DSString = formObject.getTextStreamValueAsByte(PdfDictionary.DS);
if (DSString != null) {
AnnotationFactory.loadFontValues(DSString, curComp, scale);
} else {
curComp.setFont(curComp.getFont().deriveFont(formObject.getFontSize()));
}
} else {
if (formObject.getParameterConstant(PdfDictionary.Subtype) != PdfDictionary.Popup) {
recalcFontSize(scale, rotate, formObject, curComp);
} else {
if (isPrinting) {
curComp.setFont(curComp.getFont().deriveFont(formObject.getFontSize() * (72.0f / 96.0f)));
} else {
curComp.setFont(curComp.getFont().deriveFont(formObject.getFontSize()));
}
}
}
}
//scale border if needed
if ((curComp instanceof JComponent && ((JComponent) curComp).getBorder() != null) &&
(formObject != null)) {
((JComponent) curComp).setBorder(generateBorderfromForm(formObject, scale));
}
//factor in offset if multiple pages displayed
if (xReached != null) {
bounds[0] += xReached[curPage];
bounds[1] += yReached[curPage];
}
final int pageWidth;
if ((pageData.getRotation(curPage) + rotate) % 180 == 90) {
pageWidth = pageData.getCropBoxHeight(curPage);
} else {
pageWidth = pageData.getCropBoxWidth(curPage);
}
if (displayView == Display.CONTINUOUS) {
final double newIndent;
if (rotate == 0 || rotate == 180) {
newIndent = (widestPageNR - (pageWidth)) / 2;
} else {
newIndent = (widestPageR - (pageWidth)) / 2;
}
indent = (int) (indent + (newIndent * scale));
}
final int totalOffsetX = userX + indent + insetW;
final int totalOffsetY = userY + insetH;
final Rectangle boundRect = new Rectangle(totalOffsetX + bounds[0], totalOffsetY + bounds[1], bounds[2], bounds[3]);
curComp.setBounds(boundRect);
//rescale the icons if any
if (curComp instanceof AbstractButton) {
final AbstractButton but = ((AbstractButton) curComp);
Icon curIcon = but.getIcon();
boolean displaySingle = false;
if (displayView == Display.SINGLE_PAGE || displayView == Display.NODISPLAY) {
displaySingle = true;
}
if (curIcon instanceof FixImageIcon) {
((CustomImageIcon) curIcon).setAttributes(curComp.getWidth(), curComp.getHeight(), rotate, displaySingle);
} else if (curIcon instanceof ReadOnlyTextIcon) {
((CustomImageIcon) curIcon).setAttributes(curComp.getWidth(), curComp.getHeight(), rotate, displaySingle);
}
curIcon = but.getPressedIcon();
if (curIcon instanceof FixImageIcon) {
((CustomImageIcon) curIcon).setAttributes(curComp.getWidth(), curComp.getHeight(), rotate, displaySingle);
}
curIcon = but.getSelectedIcon();
if (curIcon instanceof FixImageIcon) {
((CustomImageIcon) curIcon).setAttributes(curComp.getWidth(), curComp.getHeight(), rotate, displaySingle);
}
curIcon = but.getRolloverIcon();
if (curIcon instanceof FixImageIcon) {
((CustomImageIcon) curIcon).setAttributes(curComp.getWidth(), curComp.getHeight(), rotate, displaySingle);
}
curIcon = but.getRolloverSelectedIcon();
if (curIcon instanceof FixImageIcon) {
((CustomImageIcon) curIcon).setAttributes(curComp.getWidth(), curComp.getHeight(), rotate, displaySingle);
}
}
}
/**
* we take in curComp as it could be a JTextField showing the selected value from a JComboBox
* also the scale and rotation could be from a print routine and not the same as the global variables
*/
private static void recalcFontSize(final float scale, final int rotate, final FormObject formObject, final Component curComp) {
final int size = GUIData.getFontSize(formObject, rotate, scale);
final Font resetFont = curComp.getFont();
final Font newFont = new Font(resetFont.getFontName(), resetFont.getStyle(), size);
curComp.setFont(newFont);
}
/**
* allows the text to be autosized at any point from anywhere by only knowing the ref.
*/
@Override
public void setAutoFontSize(final FormObject formObject) {
recalcFontSize(displayScaling, rotation, formObject, (Component) formObject.getGUIComponent());
}
/**
* returns Border as is swing specific class
*/
public static Border generateBorderfromForm(final FormObject form, final float scaling) {
float[] BC = form.getDictionary(PdfDictionary.MK).getFloatArray(PdfDictionary.BC);
if (BC == null && form.getParameterConstant(PdfDictionary.Subtype) == PdfDictionary.Screen) {
BC = form.getFloatArray(PdfDictionary.C);
}
Border newBorder = JPedalBorderFactory.createBorderStyle(form.getDictionary(PdfDictionary.BS),
FormObject.generateColor(BC),
Color.white, scaling);
if (form.isXFAObject()) {
final int[] t = form.getMatteBorderDetails();
newBorder = BorderFactory.createMatteBorder(t[0], t[3], t[2], t[1], Color.black);
}
return newBorder;
}
private int[] cropComponent(final FormObject formObject, final float s, int r, final boolean redraw, final boolean positionOnly) {
final Rectangle rect = formObject.getBoundingRectangle();
final int curPage = formObject.getPageNumber();
final float[] box = {rect.x, rect.y, rect.width + rect.x, rect.height + rect.y};
//NOTE if needs adding in ULC check SpecialOptions.SINGLE_PAGE
if (displayView != Display.SINGLE_PAGE && displayView != Display.NODISPLAY) {
r = (r + pageData.getRotation(curPage)) % 360;
}
final int cropX = pageData.getCropBoxX(curPage);
final int cropY = pageData.getCropBoxY(curPage);
final int cropW = pageData.getCropBoxWidth(curPage);
final int mediaW = pageData.getMediaBoxWidth(curPage);
final int mediaH = pageData.getMediaBoxHeight(curPage);
final int cropOtherX = (mediaW - cropW - cropX);
float x100 = 0, y100 = 0, w100 = 0, h100 = 0;
final int x;
final int y;
final int w;
final int h;
switch (r) {
case 0:
x100 = box[0];
//if we are drawing on screen take off cropX if printing or extracting we dont need to do this.
if (redraw) {
x100 -= cropX;
}
y100 = mediaH - box[3] - cropOtherY[curPage] + 1;
w100 = (box[2] - box[0]);
h100 = (box[3] - box[1]);
break;
case 90:
x100 = box[1] - cropY;
y100 = box[0] - cropX + 1;
if (!positionOnly) {
w100 = (box[3] - box[1]);
h100 = (box[2] - box[0]);
} else {
w100 = (box[2] - box[0]);
h100 = (box[3] - box[1]);
}
break;
case 180:
w100 = box[2] - box[0];
h100 = box[3] - box[1];
if (!positionOnly) {
y100 = box[1] - cropY + 1;
x100 = mediaW - box[2] - cropOtherX;
} else {
w100 = (box[2] - box[0]);
h100 = (box[3] - box[1]);
}
break;
case 270:
if (!positionOnly) {
w100 = (box[3] - box[1]);
h100 = (box[2] - box[0]);
} else {
w100 = (box[2] - box[0]);
h100 = (box[3] - box[1]);
}
x100 = mediaH - box[3] - cropOtherY[curPage];
y100 = mediaW - box[2] - cropOtherX + 1;
break;
}
x = (int) (x100 * s);
y = (int) (y100 * s);
if (!positionOnly) {
w = (int) (w100 * s);
h = (int) (h100 * s);
} else {
//Don't forget to factor in the resolution of the display
w = (int) (w100 * dpi / 72);
h = (int) (h100 * dpi / 72);
}
return new int[]{x, y, w, h};
}
/**
* used to remove all components from display
*/
@Override
protected void removeAllComponentsFromScreen() {
//System.out.println("removeAllComponentsFromScreen");
//01032012 be care if you ever re-enable as big performace hit on Abacus code (see slow.pdf)
// Iterator formIter = rawFormData.values().iterator();
// while(formIter.hasNext()){
// FormObject formObj = (FormObject)formIter.next();
// pdfDecoder.getFormRenderer().getActionHandler().PI(formObj,PdfDictionary.AA);
// pdfDecoder.getFormRenderer().getActionHandler().PI(formObj,PdfDictionary.A);
// pdfDecoder.getFormRenderer().getActionHandler().PC(formObj,PdfDictionary.AA);
// pdfDecoder.getFormRenderer().getActionHandler().PC(formObj,PdfDictionary.A);
// }
if (panel != null) {
if (SwingUtilities.isEventDispatchThread()) {
panel.removeAll();
} else {
final Runnable doPaintComponent = new Runnable() {
@Override
public void run() {
panel.removeAll();
}
};
SwingUtilities.invokeLater(doPaintComponent);
}
}
}
/**
* pass in object components drawn onto
*
* @param rootComp
*/
@Override
public void setRootDisplayComponent(final Object rootComp) {
if (SwingUtilities.isEventDispatchThread()) {
panel = (JPanel) rootComp;
} else {
final Runnable doPaintComponent = new Runnable() {
@Override
public void run() {
panel = (JPanel) rootComp;
}
};
SwingUtilities.invokeLater(doPaintComponent);
}
}
@Override
public void setGUIComp(final FormObject formObject, final Object rawField) {
final Component retComponent = (Component) rawField;
//append state to name so we can retrieve later if needed
String name2 = formObject.getTextStreamValue(PdfDictionary.T);
if (name2 != null) { //we have some empty values as well as null
final String stateToCheck = formObject.getNormalOnState();
if (stateToCheck != null && !stateToCheck.isEmpty()) {
name2 = name2 + "-(" + stateToCheck + ')';
}
retComponent.setName(name2);
}
//make visible
scaleComponent(formObject, displayScaling, rotation, retComponent, true, indent, false);
}
/**
* alter location and bounds so form objects show correctly scaled
*/
@Override
public void resetScaledLocation(final float currentScaling, final int currentRotation, final int currentIndent) {
// we get a spurious call in linux resulting in an exception
if (formsUnordered == null || panel == null || startPage == 0) {
return;
}
// needed as code called recursively otherwise
if (forceRedraw || currentScaling != lastScaling || currentRotation != oldRotation || currentIndent != oldIndent) { // || SwingUtilities.isEventDispatchThread()) {
oldRotation = currentRotation;
lastScaling = currentScaling;
oldIndent = currentIndent;
forceRedraw = false;
FormObject formObject;
Component rawComp;
int count;
for (int currentPage = startPage; currentPage < endPage; currentPage++) {
if (formsOrdered[currentPage] == null) {
count = 0;
} else {
count = formsOrdered[currentPage].size();
}
// reset all locations
for (int j = 0; j < count; j++) {
formObject = formsOrdered[currentPage].get(j); //example where order matters see 19071
formObject.setCurrentScaling(currentScaling);
rawComp = (Component) formObject.getGUIComponent();
if (rawComp != null) {
if (formObject.getBoundingRectangle().height < rawComp.getPreferredSize().height && rawComp instanceof JList) { //rawComp!=null check for xfa
final JList comp = (JList) rawComp;
rawComp = wrapComponentInScrollPane(comp);
formObject.setGUIComponent(comp, FormFactory.SWING);
// ensure visible (do it before we add)
final int index = comp.getSelectedIndex();
if (index > -1) {
comp.ensureIndexIsVisible(index);
}
}
if (SwingUtilities.isEventDispatchThread()) {
panel.remove(rawComp);
scaleComponent(formObject, currentScaling, currentRotation, rawComp, true, indent, false);
panel.add(rawComp);
} else {
final Component finalComp = rawComp;
final FormObject fo = formObject;
final Runnable doPaintComponent = new Runnable() {
@Override
public void run() {
panel.remove(finalComp);
scaleComponent(fo, currentScaling, currentRotation, finalComp, true, indent, false);
panel.add(finalComp);
}
};
SwingUtilities.invokeLater(doPaintComponent);
}
}
}
}
//Validate after adding components to ensure they appear.
//Popups will sometimes vanish otherwise.
panel.validate();
}
}
/**
* forms on invisible pages need removing as we do not update their position and they will appear when we scroll otherwise
*
* @param startPage
* @param endPage
*/
@Override
void removeHiddenForms(final int startPage, final int endPage) {
FormObject formObject;
Object comp;
for (int page = startPage; page < endPage; page++) {
//get unsorted components and iterate over forms
if (formsOrdered[page] != null) {
for (final FormObject o : formsOrdered[page]) {
if (o != null) {
formObject = o;
comp = formObject.getGUIComponent();
if (comp != null) {
panel.remove((Component) comp);
}
}
}
}
}
}
private static Component wrapComponentInScrollPane(final JList comp) {
final JScrollPane scroll = new JScrollPane(comp);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setLocation(comp.getLocation());
scroll.setPreferredSize(comp.getPreferredSize());
scroll.setSize(comp.getSize());
return scroll;
}
@Override
protected void displayComponent(final FormObject formObject, final Object comp) {
if (SwingUtilities.isEventDispatchThread()) {
scaleComponent(formObject, displayScaling, rotation, (Component) comp, true, indent, false);
} else {
final Runnable doPaintComponent = new Runnable() {
@Override
public void run() {
scaleComponent(formObject, displayScaling, rotation, (Component) comp, true, indent, false);
}
};
SwingUtilities.invokeLater(doPaintComponent);
}
}
@Override
public void setCustomPrintInterface(final CustomFormPrint customFormPrint) {
this.customFormPrint = customFormPrint;
}
}