You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2019/01/17 18:52:48 UTC
svn commit: r1851572 - in
/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form:
CreateCheckBox.java CreateRadioButtons.java
Author: tilman
Date: Thu Jan 17 18:52:48 2019
New Revision: 1851572
URL: http://svn.apache.org/viewvc?rev=1851572&view=rev
Log:
PDFBOX-4434: Create flexible CheckBox and RadioButtons example
Added:
pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java (with props)
pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java (with props)
Added: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java?rev=1851572&view=auto
==============================================================================
--- pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java (added)
+++ pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java Thu Jan 17 18:52:48 2019
@@ -0,0 +1,183 @@
+/*
+ * 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.examples.interactive.form;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderStyleDictionary;
+import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDCheckBox;
+
+/**
+ * Example to create a checkbox.
+ *
+ * @author Tilman Hausherr
+ */
+public class CreateCheckBox
+{
+ public static void main(String arg[]) throws IOException
+ {
+ PDDocument document = new PDDocument();
+ PDPage page = new PDPage();
+ document.addPage(page);
+
+ PDAcroForm acroForm = new PDAcroForm(document);
+ document.getDocumentCatalog().setAcroForm(acroForm);
+
+ // if you want to see what Adobe does, activate this, open with Adobe
+ // save the file, and then open it with PDFDebugger
+ //acroForm.setNeedAppearances(true)
+
+ float x = 50;
+ float y = page.getMediaBox().getHeight() - 50;
+
+ PDRectangle rect = new PDRectangle(x, y, 20, 20);
+
+ PDCheckBox checkbox = new PDCheckBox(acroForm);
+ checkbox.setPartialName("MyCheckBox");
+ PDAnnotationWidget widget = checkbox.getWidgets().get(0);
+ widget.setPage(page);
+ widget.setRectangle(rect);
+ widget.setPrinted(true);
+
+ PDAppearanceCharacteristicsDictionary appearanceCharacteristics = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
+ appearanceCharacteristics.setBorderColour(new PDColor(new float[]{1, 0, 0}, PDDeviceRGB.INSTANCE));
+ appearanceCharacteristics.setBackground(new PDColor(new float[]{1, 1, 0}, PDDeviceRGB.INSTANCE));
+ // 8 = cross; 4 = checkmark; H = star; u = diamond; n = square, l = dot
+ appearanceCharacteristics.setNormalCaption("4");
+ widget.setAppearanceCharacteristics(appearanceCharacteristics);
+
+ PDBorderStyleDictionary borderStyleDictionary = new PDBorderStyleDictionary();
+ borderStyleDictionary.setWidth(1);
+ borderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_SOLID);
+ widget.setBorderStyle(borderStyleDictionary);
+
+ PDAppearanceDictionary ap = new PDAppearanceDictionary();
+ widget.setAppearance(ap);
+ PDAppearanceEntry normalAppearance = ap.getNormalAppearance();
+
+ COSDictionary normalAppearanceDict = (COSDictionary) normalAppearance.getCOSObject();
+ normalAppearanceDict.setItem(COSName.Off, createRadioButtonAppearanceStream(document, widget, false));
+ normalAppearanceDict.setItem(COSName.YES, createRadioButtonAppearanceStream(document, widget, true));
+
+ // If we ever decide to implement a /D (down) appearance, just
+ // replace the background colors c with c * 0.75
+ page.getAnnotations().add(checkbox.getWidgets().get(0));
+ acroForm.getFields().add(checkbox);
+
+ checkbox.check();
+
+ document.save("CheckBoxSample.pdf");
+ document.close();
+ }
+
+ private static PDAppearanceStream createRadioButtonAppearanceStream(
+ final PDDocument document, PDAnnotationWidget widget, boolean on) throws IOException
+ {
+ PDRectangle rect = widget.getRectangle();
+ PDAppearanceCharacteristicsDictionary appearanceCharacteristics;
+ PDAppearanceStream yesAP = new PDAppearanceStream(document);
+ yesAP.setBBox(new PDRectangle(rect.getWidth(), rect.getHeight()));
+ yesAP.setResources(new PDResources());
+ PDPageContentStream yesAPCS = new PDPageContentStream(document, yesAP);
+ appearanceCharacteristics = widget.getAppearanceCharacteristics();
+ PDColor backgroundColor = appearanceCharacteristics.getBackground();
+ PDColor borderColor = appearanceCharacteristics.getBorderColour();
+ float lineWidth = getLineWidth(widget);
+ yesAPCS.setLineWidth(lineWidth); // border style (dash) ignored
+ yesAPCS.setNonStrokingColor(backgroundColor);
+ yesAPCS.addRect(0, 0, rect.getWidth(), rect.getHeight());
+ yesAPCS.fill();
+ yesAPCS.setStrokingColor(borderColor);
+ yesAPCS.addRect(lineWidth / 2, lineWidth / 2, rect.getWidth() - lineWidth, rect.getHeight() - lineWidth);
+ yesAPCS.stroke();
+ if (!on)
+ {
+ yesAPCS.close();
+ return yesAP;
+ }
+
+ yesAPCS.addRect(lineWidth, lineWidth, rect.getWidth() - lineWidth * 2, rect.getHeight() - lineWidth * 2);
+ yesAPCS.clip();
+
+ String normalCaption = appearanceCharacteristics.getNormalCaption();
+ if (normalCaption == null)
+ {
+ normalCaption = "4"; // Adobe behaviour
+ }
+ if ("8".equals(normalCaption))
+ {
+ // Adobe paints a cross instead of using the Zapf Dingbats cross symbol
+ yesAPCS.setStrokingColor(0f);
+ yesAPCS.moveTo(lineWidth * 2, rect.getHeight() - lineWidth * 2);
+ yesAPCS.lineTo(rect.getWidth() - lineWidth * 2, lineWidth * 2);
+ yesAPCS.moveTo(rect.getWidth() - lineWidth * 2, rect.getHeight() - lineWidth * 2);
+ yesAPCS.lineTo(lineWidth * 2, lineWidth * 2);
+ yesAPCS.stroke();
+ }
+ else
+ {
+ // The caption is not unicode, but the Zapf Dingbats code in the PDF
+ // Thus convert it back to unicode
+ // Assume that only the first character is used.
+ String name = PDType1Font.ZAPF_DINGBATS.codeToName(normalCaption.codePointAt(0));
+ String unicode = PDType1Font.ZAPF_DINGBATS.getGlyphList().toUnicode(name);
+ Rectangle2D bounds = PDType1Font.ZAPF_DINGBATS.getPath(name).getBounds2D();
+ float size = (float) Math.min(bounds.getWidth(), bounds.getHeight()) / 1000;
+ // assume that checkmark has square size
+ // the calculations approximate what Adobe is doing, i.e. put the glyph in the middle
+ float fontSize = (rect.getWidth() - lineWidth * 2) / size * 0.6666f;
+ float xOffset = (float) (rect.getWidth() - (bounds.getWidth()) / 1000 * fontSize) / 2;
+ xOffset -= bounds.getX() / 1000 * fontSize;
+ float yOffset = (float) (rect.getHeight() - (bounds.getHeight()) / 1000 * fontSize) / 2;
+ yOffset -= bounds.getY() / 1000 * fontSize;
+ yesAPCS.setNonStrokingColor(0f);
+ yesAPCS.beginText();
+ yesAPCS.setFont(PDType1Font.ZAPF_DINGBATS, fontSize);
+ yesAPCS.newLineAtOffset(xOffset, yOffset);
+ yesAPCS.showText(unicode);
+ yesAPCS.endText();
+ }
+ yesAPCS.close();
+ return yesAP;
+ }
+
+ static float getLineWidth(PDAnnotationWidget widget)
+ {
+ PDBorderStyleDictionary bs = widget.getBorderStyle();
+ if (bs != null)
+ {
+ return bs.getWidth();
+ }
+ return 1;
+ }
+}
Propchange: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java?rev=1851572&view=auto
==============================================================================
--- pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java (added)
+++ pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java Thu Jan 17 18:52:48 2019
@@ -0,0 +1,170 @@
+/*
+ * 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.examples.interactive.form;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderStyleDictionary;
+import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDRadioButton;
+
+/**
+ * Example to create radio buttons.
+ *
+ * @author Tilman Hausherr
+ */
+public class CreateRadioButtons
+{
+ public static void main(String[] args) throws IOException
+ {
+ PDDocument document = new PDDocument();
+ PDPage page = new PDPage(PDRectangle.A4);
+ document.addPage(page);
+ PDAcroForm acroForm = new PDAcroForm(document);
+
+ // if you want to see what Adobe does, activate this, open with Adobe
+ // save the file, and then open it with PDFDebugger
+
+ //acroForm.setNeedAppearances(true)
+
+ document.getDocumentCatalog().setAcroForm(acroForm);
+ List<String> options = Arrays.asList("a", "b", "c");
+ PDRadioButton radioButton = new PDRadioButton(acroForm);
+ radioButton.setPartialName("MyRadioButton");
+ radioButton.setExportValues(options);
+
+ PDAppearanceCharacteristicsDictionary appearanceCharacteristics = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
+ appearanceCharacteristics.setBorderColour(new PDColor(new float[] { 1, 0, 0 }, PDDeviceRGB.INSTANCE));
+ appearanceCharacteristics.setBackground(new PDColor(new float[]{0, 1, 0.3f}, PDDeviceRGB.INSTANCE));
+ // no caption => round
+ // with caption => see checkbox example
+
+ List<PDAnnotationWidget> widgets = new ArrayList<PDAnnotationWidget>();
+ for (int i = 0; i < options.size(); i++)
+ {
+ PDAnnotationWidget widget = new PDAnnotationWidget();
+ widget.setRectangle(new PDRectangle(30, PDRectangle.A4.getHeight() - 40 - i * 35, 30, 30));
+ widget.setAppearanceCharacteristics(appearanceCharacteristics);
+ PDBorderStyleDictionary borderStyleDictionary = new PDBorderStyleDictionary();
+ borderStyleDictionary.setWidth(2);
+ borderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_SOLID);
+ widget.setBorderStyle(borderStyleDictionary);
+ widget.setPage(page);
+
+ COSDictionary apNDict = new COSDictionary();
+ apNDict.setItem(COSName.Off, createCheckBoxAppearanceStream(document, widget, false));
+ apNDict.setItem(options.get(i), createCheckBoxAppearanceStream(document, widget, true));
+
+ PDAppearanceDictionary appearance = new PDAppearanceDictionary();
+ PDAppearanceEntry appearanceNEntry = new PDAppearanceEntry(apNDict);
+ appearance.setNormalAppearance(appearanceNEntry);
+ widget.setAppearance(appearance);
+ widget.setAppearanceState("Off"); // don't forget this, or button will be invisible
+ widgets.add(widget);
+ page.getAnnotations().add(widget);
+ }
+ radioButton.setWidgets(widgets);
+
+ acroForm.getFields().add(radioButton);
+
+ // Set the texts
+ PDPageContentStream contents = new PDPageContentStream(document, page);
+ for (int i = 0; i < options.size(); i++)
+ {
+ contents.beginText();
+ contents.setFont(PDType1Font.HELVETICA, 15);
+ contents.newLineAtOffset(70, PDRectangle.A4.getHeight() - 30 - i * 35);
+ contents.showText(options.get(i));
+ contents.endText();
+ }
+ contents.close();
+
+ radioButton.setValue("c");
+
+ document.save("RadioButtonsSample.pdf");
+ document.close();
+ }
+
+ private static PDAppearanceStream createCheckBoxAppearanceStream(
+ final PDDocument document, PDAnnotationWidget widget, boolean on) throws IOException
+ {
+ PDRectangle rect = widget.getRectangle();
+ PDAppearanceStream onAP = new PDAppearanceStream(document);
+ onAP.setBBox(new PDRectangle(rect.getWidth(), rect.getHeight()));
+ PDPageContentStream onAPCS = new PDPageContentStream(document, onAP);
+
+ PDAppearanceCharacteristicsDictionary appearanceCharacteristics = widget.getAppearanceCharacteristics();
+ PDColor backgroundColor = appearanceCharacteristics.getBackground();
+ PDColor borderColor = appearanceCharacteristics.getBorderColour();
+ float lineWidth = getLineWidth(widget);
+ onAPCS.setLineWidth(lineWidth); // border style (dash) ignored
+ onAPCS.setNonStrokingColor(backgroundColor);
+ float radius = Math.min(rect.getWidth() / 2, rect.getHeight() / 2);
+ drawCircle(onAPCS, rect.getWidth() / 2, rect.getHeight() / 2, radius);
+ onAPCS.fill();
+ onAPCS.setStrokingColor(borderColor);
+ drawCircle(onAPCS, rect.getWidth() / 2, rect.getHeight() / 2, radius - lineWidth / 2);
+ onAPCS.stroke();
+ if (on)
+ {
+ onAPCS.setNonStrokingColor(0f);
+ drawCircle(onAPCS, rect.getWidth() / 2, rect.getHeight() / 2, (radius - lineWidth) / 2);
+ onAPCS.fill();
+ }
+
+ onAPCS.close();
+ return onAP;
+ }
+
+ static float getLineWidth(PDAnnotationWidget widget)
+ {
+ PDBorderStyleDictionary bs = widget.getBorderStyle();
+ if (bs != null)
+ {
+ return bs.getWidth();
+ }
+ return 1;
+ }
+
+ static void drawCircle(PDPageContentStream cs, float x, float y, float r) throws IOException
+ {
+ // http://stackoverflow.com/a/2007782/535646
+ float magic = r * 0.551784f;
+ cs.moveTo(x, y + r);
+ cs.curveTo(x + magic, y + r, x + r, y + magic, x + r, y);
+ cs.curveTo(x + r, y - magic, x + magic, y - r, x, y - r);
+ cs.curveTo(x - magic, y - r, x - r, y - magic, x - r, y);
+ cs.curveTo(x - r, y + magic, x - magic, y + r, x, y + r);
+ cs.closePath();
+ }
+}
Propchange: pdfbox/branches/2.0/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
------------------------------------------------------------------------------
svn:eol-style = native