pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From til...@apache.org
Subject svn commit: r1851571 - in /pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form: CreateCheckBox.java CreateRadioButtons.java
Date Thu, 17 Jan 2019 18:52:41 GMT
Author: tilman
Date: Thu Jan 17 18:52:41 2019
New Revision: 1851571

URL: http://svn.apache.org/viewvc?rev=1851571&view=rev
Log:
PDFBOX-4434: Create flexible CheckBox and RadioButtons example

Added:
    pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
  (with props)
    pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
  (with props)

Added: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java?rev=1851571&view=auto
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
(added)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
Thu Jan 17 18:52:41 2019
@@ -0,0 +1,187 @@
+/*
+ * 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.PDAppearanceContentStream;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+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
+    {
+        try (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");
+        }
+    }
+
+    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());
+        try (PDAppearanceContentStream yesAPCS = new PDAppearanceContentStream(yesAP))
+        {
+            appearanceCharacteristics = widget.getAppearanceCharacteristics();
+            PDColor backgroundColor = appearanceCharacteristics.getBackground();
+            PDColor borderColor = appearanceCharacteristics.getBorderColour();
+            float lineWidth = getLineWidth(widget);
+            yesAPCS.setBorderLine(lineWidth, widget.getBorderStyle(), widget.getBorder());
+            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)
+            {
+                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(0);
+                yesAPCS.beginText();
+                yesAPCS.setFont(PDType1Font.ZAPF_DINGBATS, fontSize);
+                yesAPCS.newLineAtOffset(xOffset, yOffset);
+                yesAPCS.showText(unicode);
+                yesAPCS.endText();
+            }
+        }
+        return yesAP;
+    }
+
+    static float getLineWidth(PDAnnotationWidget widget)
+    {
+        PDBorderStyleDictionary bs = widget.getBorderStyle();
+        if (bs != null)
+        {
+            return bs.getWidth();
+        }
+        return 1;
+    }
+}

Propchange: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateCheckBox.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java?rev=1851571&view=auto
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
(added)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
Thu Jan 17 18:52:41 2019
@@ -0,0 +1,172 @@
+/*
+ * 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.PDAppearanceContentStream;
+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
+    {
+        try (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<>();
+            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
+            try (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();
+                }
+            }
+            
+            radioButton.setValue("c");
+
+            document.save("RadioButtonsSample.pdf");
+        }
+    }
+
+    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()));
+        try (PDAppearanceContentStream onAPCS = new PDAppearanceContentStream(onAP))
+        {
+            PDAppearanceCharacteristicsDictionary appearanceCharacteristics = widget.getAppearanceCharacteristics();
+            PDColor backgroundColor = appearanceCharacteristics.getBackground();
+            PDColor borderColor = appearanceCharacteristics.getBorderColour();
+            float lineWidth = getLineWidth(widget);
+            onAPCS.setBorderLine(lineWidth, widget.getBorderStyle(), widget.getBorder());
+            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();
+            }
+        }
+        return onAP;
+    }
+
+    static float getLineWidth(PDAnnotationWidget widget)
+    {
+        PDBorderStyleDictionary bs = widget.getBorderStyle();
+        if (bs != null)
+        {
+            return bs.getWidth();
+        }
+        return 1;
+    }
+
+    static void drawCircle(PDAppearanceContentStream 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/trunk/examples/src/main/java/org/apache/pdfbox/examples/interactive/form/CreateRadioButtons.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message