Skip to content

Commit 0965f96

Browse files
pavel-alayiText-CI
authored andcommitted
Fetch Normal appearance as PdfDictionary or as PdfStream
DEVSIX-2421 SUP-3570
1 parent 577fee0 commit 0965f96

File tree

4 files changed

+207
-3
lines changed

4 files changed

+207
-3
lines changed

forms/src/main/java/com/itextpdf/forms/fields/PdfFormField.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ public static PdfButtonFormField createRadioGroup(PdfDocument doc, String name,
755755
* @param radioGroup the radio button group that this field should belong to
756756
* @param value the initial value
757757
* @return a new {@link PdfFormField}
758-
* @see #createRadioGroup(com.itextpdf.kernel.pdf.PdfDocument, java.lang.String, java.lang.String)
758+
* @see #createRadioGroup(PdfDocument, java.lang.String, java.lang.String)
759759
*/
760760
public static PdfFormField createRadioButton(PdfDocument doc, Rectangle rect, PdfButtonFormField radioGroup, String value) {
761761
PdfWidgetAnnotation annot = new PdfWidgetAnnotation(rect);
@@ -781,7 +781,7 @@ public static PdfFormField createRadioButton(PdfDocument doc, Rectangle rect, Pd
781781
* @param value the initial value
782782
* @param pdfAConformanceLevel the {@link PdfAConformanceLevel} of the document. {@code} null if it's no PDF/A document
783783
* @return a new {@link PdfFormField}
784-
* @see #createRadioGroup(com.itextpdf.kernel.pdf.PdfDocument, java.lang.String, java.lang.String)
784+
* @see #createRadioGroup(PdfDocument, java.lang.String, java.lang.String)
785785
*/
786786
public static PdfFormField createRadioButton(PdfDocument doc, Rectangle rect, PdfButtonFormField radioGroup, String value, PdfAConformanceLevel pdfAConformanceLevel) {
787787
PdfWidgetAnnotation annot = new PdfWidgetAnnotation(rect);
@@ -1941,6 +1941,7 @@ public boolean regenerateField() {
19411941
PdfDictionary apDic = getPdfObject().getAsDictionary(PdfName.AP);
19421942
PdfStream asNormal = null;
19431943
if (apDic != null) {
1944+
//TODO DEVSIX-2528 what if PdfName.N is PdfDictionary?
19441945
asNormal = apDic.getAsStream(PdfName.N);
19451946
}
19461947
PdfArray bBox = getPdfObject().getAsArray(PdfName.Rect);
@@ -2097,6 +2098,7 @@ public boolean regenerateField() {
20972098
} else {
20982099
PdfStream asNormal = null;
20992100
if (apDic != null) {
2101+
//TODO DEVSIX-2528 what is PdfName.N is PdfDictionary?
21002102
asNormal = apDic.getAsStream(PdfName.N);
21012103
}
21022104
Object[] fontAndSize = getFontAndSize(asNormal);
@@ -2124,7 +2126,7 @@ public boolean regenerateField() {
21242126
PdfWidgetAnnotation widget = field.getWidgets().get(0);
21252127
PdfDictionary apStream = field.getPdfObject().getAsDictionary(PdfName.AP);
21262128
String state;
2127-
if (null != apStream && null != apStream.getAsDictionary(PdfName.N).get(new PdfName(value))) {
2129+
if (null != apStream && null != getValueFromAppearance(apStream.get(PdfName.N), new PdfName(value))) {
21282130
state = value;
21292131
} else {
21302132
state = "Off";
@@ -2494,6 +2496,7 @@ public String[] getAppearanceStates() {
24942496
PdfDictionary dic = getPdfObject();
24952497
dic = dic.getAsDictionary(PdfName.AP);
24962498
if (dic != null) {
2499+
//TODO DEVSIX-2528 what if PdfName.N is PdfDictionary?
24972500
dic = dic.getAsDictionary(PdfName.N);
24982501
if (dic != null) {
24992502
for (PdfName state : dic.keySet()) {
@@ -3369,4 +3372,11 @@ private static String optionsArrayToString(PdfArray options) {
33693372
private static double degreeToRadians(double angle) {
33703373
return Math.PI * angle / 180.0;
33713374
}
3375+
3376+
private PdfObject getValueFromAppearance(PdfObject appearanceDict, PdfName key) {
3377+
if (appearanceDict instanceof PdfDictionary) {
3378+
return ((PdfDictionary)appearanceDict).get(key);
3379+
}
3380+
return null;
3381+
}
33723382
}

pdfa/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
<version>${project.version}</version>
2222
<scope>test</scope>
2323
</dependency>
24+
<dependency>
25+
<groupId>com.itextpdf</groupId>
26+
<artifactId>forms</artifactId>
27+
<version>${project.version}</version>
28+
<scope>test</scope>
29+
</dependency>
2430
</dependencies>
2531
<build>
2632
<plugins>
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2018 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License version 3
8+
as published by the Free Software Foundation with the addition of the
9+
following permission added to Section 15 as permitted in Section 7(a):
10+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
11+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
12+
OF THIRD PARTY RIGHTS
13+
14+
This program is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE.
17+
See the GNU Affero General Public License for more details.
18+
You should have received a copy of the GNU Affero General Public License
19+
along with this program; if not, see http://www.gnu.org/licenses or write to
20+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
22+
http://itextpdf.com/terms-of-use/
23+
24+
The interactive user interfaces in modified source and object code versions
25+
of this program must display Appropriate Legal Notices, as required under
26+
Section 5 of the GNU Affero General Public License.
27+
28+
In accordance with Section 7(b) of the GNU Affero General Public License,
29+
a covered work must retain the producer line in every PDF that is created
30+
or manipulated using iText.
31+
32+
You can be released from the requirements of the license by purchasing
33+
a commercial license. Buying such a license is mandatory as soon as you
34+
develop commercial activities involving the iText software without
35+
disclosing the source code of your own applications.
36+
These activities include: offering paid services to customers as an ASP,
37+
serving PDFs on the fly in a web application, shipping iText with a closed
38+
source product.
39+
40+
For more information, please contact iText Software Corp. at this
41+
42+
*/
43+
package com.itextpdf.pdfa;
44+
45+
import com.itextpdf.forms.PdfAcroForm;
46+
import com.itextpdf.forms.fields.PdfButtonFormField;
47+
import com.itextpdf.forms.fields.PdfFormField;
48+
import com.itextpdf.kernel.colors.ColorConstants;
49+
import com.itextpdf.kernel.font.PdfFont;
50+
import com.itextpdf.kernel.font.PdfFontFactory;
51+
import com.itextpdf.kernel.geom.PageSize;
52+
import com.itextpdf.kernel.geom.Rectangle;
53+
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
54+
import com.itextpdf.kernel.pdf.PdfDocument;
55+
import com.itextpdf.kernel.pdf.PdfName;
56+
import com.itextpdf.kernel.pdf.PdfOutputIntent;
57+
import com.itextpdf.kernel.pdf.PdfWriter;
58+
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
59+
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
60+
import com.itextpdf.kernel.utils.CompareTool;
61+
import com.itextpdf.layout.Document;
62+
import com.itextpdf.layout.element.Image;
63+
import com.itextpdf.layout.element.Paragraph;
64+
import com.itextpdf.layout.element.Text;
65+
import com.itextpdf.layout.renderer.DrawContext;
66+
import com.itextpdf.layout.renderer.ParagraphRenderer;
67+
import com.itextpdf.test.ExtendedITextTest;
68+
import com.itextpdf.test.annotations.type.IntegrationTest;
69+
import org.junit.Assert;
70+
import org.junit.BeforeClass;
71+
import org.junit.Test;
72+
import org.junit.experimental.categories.Category;
73+
74+
import java.io.FileInputStream;
75+
import java.io.FileOutputStream;
76+
import java.io.InputStream;
77+
78+
@Category(IntegrationTest.class)
79+
public class PdfAFormFieldTest extends ExtendedITextTest {
80+
81+
public static final String sourceFolder = "./src/test/resources/com/itextpdf/pdfa/";
82+
public static final String destinationFolder = "./target/test/com/itextpdf/pdfa/PdfAFormFieldTest/";
83+
84+
@BeforeClass
85+
public static void beforeClass() {
86+
createDestinationFolder(destinationFolder);
87+
}
88+
89+
@Test
90+
public void pdfAButtonFieldTest() throws Exception {
91+
PdfDocument pdf;
92+
InputStream is = new FileInputStream(sourceFolder + "sRGB Color Space Profile.icm");
93+
String file = "pdfAButtonField.pdf";
94+
String filename = destinationFolder + file;
95+
pdf = new PdfADocument(
96+
new PdfWriter(new FileOutputStream(filename)),
97+
PdfAConformanceLevel.PDF_A_1B,
98+
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB ICC preference", is));
99+
100+
PageSize pageSize = PageSize.LETTER;
101+
Document doc = new Document(pdf, pageSize);
102+
PdfFontFactory.register(sourceFolder + "FreeSans.ttf",sourceFolder + "FreeSans.ttf");
103+
PdfFont font = PdfFontFactory.createFont(sourceFolder + "FreeSans.ttf", true);
104+
105+
PdfButtonFormField group = PdfFormField.createRadioGroup(pdf, "group", "", PdfAConformanceLevel.PDF_A_1B);
106+
group.setReadOnly(true);
107+
108+
Paragraph p = new Paragraph();
109+
Text t = new Text("supported");
110+
111+
t.setFont(font);
112+
113+
p.add(t);
114+
115+
Image ph = new Image(new PdfFormXObject(new Rectangle(10, 10)));
116+
Paragraph pc = new Paragraph().add(ph);
117+
PdfAButtonFieldTestRenderer r = new PdfAButtonFieldTestRenderer(pc, group, "v1");
118+
119+
pc.setNextRenderer(r);
120+
121+
p.add(pc);
122+
123+
Paragraph pc1 = new Paragraph().add(ph);
124+
PdfAButtonFieldTestRenderer r1 = new PdfAButtonFieldTestRenderer(pc, group, "v2");
125+
pc1.setNextRenderer(r1);
126+
127+
Paragraph p2 = new Paragraph();
128+
Text t2 = new Text("supported 2");
129+
t2.setFont(font);
130+
131+
p2.add(t2).add(pc1);
132+
133+
doc.add(p);
134+
doc.add(p2);
135+
group.setValue("v1");
136+
137+
pdf.close();
138+
Assert.assertNull(new CompareTool().compareByContent(filename, sourceFolder + "cmp_" + file, destinationFolder, "diff_"));
139+
}
140+
141+
static class PdfAButtonFieldTestRenderer extends ParagraphRenderer {
142+
private PdfButtonFormField _group;
143+
private String _value;
144+
145+
public PdfAButtonFieldTestRenderer(Paragraph para, PdfButtonFormField group, String value)
146+
{
147+
super(para);
148+
_group = group;
149+
_value = value;
150+
}
151+
152+
@Override
153+
public void draw(DrawContext context)
154+
{
155+
int pageNumber = getOccupiedArea().getPageNumber();
156+
Rectangle bbox = getInnerAreaBBox();
157+
PdfDocument pdf = context.getDocument();
158+
PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
159+
PdfFormField chk = PdfFormField.createRadioButton(pdf, bbox, _group, _value, PdfAConformanceLevel.PDF_A_1B);
160+
chk.setPage(pageNumber);
161+
chk.setValue("Off");
162+
chk.regenerateField();
163+
164+
chk.setVisibility(PdfFormField.VISIBLE);
165+
chk.setBorderColor(ColorConstants.BLACK);
166+
chk.setBackgroundColor(ColorConstants.WHITE);
167+
chk.setReadOnly(true);
168+
169+
PdfFormXObject appearance = new PdfFormXObject(bbox);
170+
PdfCanvas canvas = new PdfCanvas(appearance, pdf);
171+
172+
canvas.saveState()
173+
.moveTo(bbox.getLeft(), bbox.getBottom())
174+
.lineTo(bbox.getRight(), bbox.getBottom())
175+
.lineTo(bbox.getRight(), bbox.getTop())
176+
.lineTo(bbox.getLeft(), bbox.getTop())
177+
.lineTo(bbox.getLeft(), bbox.getBottom())
178+
.setLineWidth(1f)
179+
.stroke()
180+
.restoreState();
181+
182+
form.addFieldAppearanceToPage(chk, pdf.getPage(pageNumber));
183+
chk.setAppearance(PdfName.N, "v1".equals(_value) ? _value : "Off", appearance.getPdfObject());
184+
}
185+
}
186+
}
187+
188+
Binary file not shown.

0 commit comments

Comments
 (0)