Skip to content

Commit bbc54de

Browse files
pavel-alayiText-CI
authored andcommitted
Fix radio button field regeneration
DEVSIX-2408 Autoported commit. Original commit hash: [0c65942f3]
1 parent 7f1cc60 commit bbc54de

File tree

7 files changed

+131
-34
lines changed

7 files changed

+131
-34
lines changed

itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,8 @@ public virtual void ButtonFieldTest01() {
221221
/// <exception cref="System.IO.IOException"/>
222222
/// <exception cref="System.Exception"/>
223223
[NUnit.Framework.Test]
224-
public virtual void RadiobuttonFieldTest01() {
225-
//TODO DEVSIX-2408
226-
String file = "radiobuttonFieldTest01.pdf";
224+
public virtual void DefaultRadiobuttonFieldTest() {
225+
String file = "defaultRadiobuttonFieldTest.pdf";
227226
String filename = destinationFolder + file;
228227
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename));
229228
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
@@ -233,16 +232,48 @@ public virtual void RadiobuttonFieldTest01() {
233232
PdfFormField.CreateRadioButton(pdfDoc, rect1, group, "1");
234233
PdfFormField.CreateRadioButton(pdfDoc, rect2, group, "2");
235234
form.AddField(group);
236-
rect1 = new Rectangle(36, 600, 20, 20);
237-
rect2 = new Rectangle(36, 580, 20, 20);
238-
// TODO DEVSIX-2408
239-
// Both radio groups have the same appearances, despite additional properties.
240-
// Default value is lost for the second group.
235+
pdfDoc.Close();
236+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(filename, sourceFolder + "cmp_" + file, destinationFolder
237+
, "diff_"));
238+
}
239+
240+
/// <exception cref="System.IO.IOException"/>
241+
/// <exception cref="System.Exception"/>
242+
[NUnit.Framework.Test]
243+
public virtual void CustomizedRadiobuttonFieldTest() {
244+
String file = "customizedRadiobuttonFieldTest.pdf";
245+
String filename = destinationFolder + file;
246+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename));
247+
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
248+
Rectangle rect1 = new Rectangle(36, 700, 20, 20);
249+
Rectangle rect2 = new Rectangle(36, 680, 20, 20);
250+
PdfButtonFormField group2 = PdfFormField.CreateRadioGroup(pdfDoc, "TestGroup2", "1");
251+
PdfFormField.CreateRadioButton(pdfDoc, rect1, group2, "1").SetBorderWidth(2).SetBorderColor(ColorConstants
252+
.RED).SetBackgroundColor(ColorConstants.LIGHT_GRAY).SetVisibility(PdfFormField.VISIBLE);
253+
PdfFormField.CreateRadioButton(pdfDoc, rect2, group2, "2").SetBorderWidth(2).SetBorderColor(ColorConstants
254+
.RED).SetBackgroundColor(ColorConstants.LIGHT_GRAY).SetVisibility(PdfFormField.VISIBLE);
255+
form.AddField(group2);
256+
pdfDoc.Close();
257+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(filename, sourceFolder + "cmp_" + file, destinationFolder
258+
, "diff_"));
259+
}
260+
261+
/// <exception cref="System.IO.IOException"/>
262+
/// <exception cref="System.Exception"/>
263+
[NUnit.Framework.Test]
264+
public virtual void CustomizedRadiobuttonWithGroupRegeneratingFieldTest() {
265+
String file = "customizedRadiobuttonWithGroupRegeneratingFieldTest.pdf";
266+
String filename = destinationFolder + file;
267+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename));
268+
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
269+
Rectangle rect1 = new Rectangle(36, 700, 20, 20);
270+
Rectangle rect2 = new Rectangle(36, 680, 20, 20);
241271
PdfButtonFormField group2 = PdfFormField.CreateRadioGroup(pdfDoc, "TestGroup2", "1");
242272
PdfFormField.CreateRadioButton(pdfDoc, rect1, group2, "1").SetBorderWidth(2).SetBorderColor(ColorConstants
243-
.RED).SetBackgroundColor(ColorConstants.LIGHT_GRAY);
273+
.RED).SetBackgroundColor(ColorConstants.LIGHT_GRAY).SetVisibility(PdfFormField.VISIBLE);
244274
PdfFormField.CreateRadioButton(pdfDoc, rect2, group2, "2").SetBorderWidth(2).SetBorderColor(ColorConstants
245-
.RED).SetBackgroundColor(ColorConstants.LIGHT_GRAY);
275+
.RED).SetBackgroundColor(ColorConstants.LIGHT_GRAY).SetVisibility(PdfFormField.VISIBLE);
276+
group2.RegenerateField();
246277
form.AddField(group2);
247278
pdfDoc.Close();
248279
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(filename, sourceFolder + "cmp_" + file, destinationFolder

itext/itext.forms/itext/forms/fields/PdfFormField.cs

Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2750,21 +2750,40 @@ public virtual bool RegenerateField() {
27502750
}
27512751
else {
27522752
if ((ff & PdfButtonFormField.FF_RADIO) != 0) {
2753-
PdfArray kids = GetKids();
2754-
if (null != kids) {
2755-
for (int i = 0; i < kids.Size(); i++) {
2756-
PdfObject kid = kids.Get(i);
2757-
iText.Forms.Fields.PdfFormField field = new iText.Forms.Fields.PdfFormField((PdfDictionary)kid);
2758-
PdfWidgetAnnotation widget = field.GetWidgets()[0];
2759-
PdfDictionary apStream = field.GetPdfObject().GetAsDictionary(PdfName.AP);
2760-
String state;
2761-
if (null != apStream && null != GetValueFromAppearance(apStream.Get(PdfName.N), new PdfName(value))) {
2762-
state = value;
2753+
if (IsRadioButton()) {
2754+
// TODO DEVSIX-2536
2755+
// Actually only radio group has FF_RADIO type.
2756+
// This means that only radio group shall have regeneration functionality.
2757+
Rectangle rect = GetRect(GetPdfObject());
2758+
value = GetRadioButtonValue(value);
2759+
if (rect != null && !"".Equals(value)) {
2760+
if (pdfAConformanceLevel != null && "1".Equals(pdfAConformanceLevel.GetPart())) {
2761+
DrawPdfA1RadioAppearance(rect.GetWidth(), rect.GetHeight(), value);
27632762
}
27642763
else {
2765-
state = "Off";
2764+
DrawRadioAppearance(rect.GetWidth(), rect.GetHeight(), value);
2765+
}
2766+
}
2767+
}
2768+
else {
2769+
if (GetKids() != null) {
2770+
foreach (PdfObject kid in GetKids()) {
2771+
iText.Forms.Fields.PdfFormField field = new iText.Forms.Fields.PdfFormField((PdfDictionary)kid);
2772+
PdfWidgetAnnotation widget = field.GetWidgets()[0];
2773+
PdfDictionary apStream = field.GetPdfObject().GetAsDictionary(PdfName.AP);
2774+
if (apStream == null) {
2775+
//widget annotation was not merged
2776+
apStream = widget.GetPdfObject().GetAsDictionary(PdfName.AP);
2777+
}
2778+
PdfName state;
2779+
if (null != apStream && null != GetValueFromAppearance(apStream.Get(PdfName.N), new PdfName(value))) {
2780+
state = new PdfName(value);
2781+
}
2782+
else {
2783+
state = new PdfName("Off");
2784+
}
2785+
widget.SetAppearanceState(state);
27662786
}
2767-
widget.SetAppearanceState(new PdfName(state));
27682787
}
27692788
}
27702789
}
@@ -2812,6 +2831,49 @@ public virtual bool RegenerateField() {
28122831
return true;
28132832
}
28142833

2834+
// TODO DEVSIX-2536
2835+
// Actually this entire method is a mess,
2836+
// because only radio group has FF_RADIO type and there is no RadioButton at all.
2837+
// So the goal of that method is just to save backward compatibility until refactoring.
2838+
private bool IsRadioButton() {
2839+
if (IsWidgetAnnotation(GetPdfObject())) {
2840+
return true;
2841+
}
2842+
else {
2843+
if (GetPdfObject().GetAsName(PdfName.V) != null) {
2844+
return false;
2845+
}
2846+
else {
2847+
if (GetKids() != null) {
2848+
return IsWidgetAnnotation(GetKids().GetAsDictionary(0));
2849+
}
2850+
else {
2851+
return false;
2852+
}
2853+
}
2854+
}
2855+
}
2856+
2857+
private static bool IsWidgetAnnotation(PdfDictionary pdfObject) {
2858+
return pdfObject != null && PdfName.Widget.Equals(pdfObject.GetAsName(PdfName.Subtype));
2859+
}
2860+
2861+
private String GetRadioButtonValue(String value) {
2862+
System.Diagnostics.Debug.Assert(value != null);
2863+
//Otherwise something wrong with getValueAsString().
2864+
if ("".Equals(value)) {
2865+
value = "Yes";
2866+
//let it as default value
2867+
foreach (String state in GetAppearanceStates()) {
2868+
if (!"Off".Equals(state)) {
2869+
value = state;
2870+
break;
2871+
}
2872+
}
2873+
}
2874+
return value;
2875+
}
2876+
28152877
/// <summary>According to spec (ISO-32000-1, 12.7.3.3) zero font size should interpretaded as auto size.</summary>
28162878
private float NormalizeFontSize(float fs, PdfFont localFont, PdfArray bBox, String value) {
28172879
if (fs == 0) {
@@ -3206,7 +3268,7 @@ protected internal virtual Rectangle GetRect(PdfDictionary field) {
32063268
}
32073269
rect = ((PdfDictionary)kids.Get(0)).GetAsArray(PdfName.Rect);
32083270
}
3209-
return rect.ToRectangle();
3271+
return rect != null ? rect.ToRectangle() : null;
32103272
}
32113273

32123274
protected internal static PdfArray ProcessOptions(String[][] options) {
@@ -3593,27 +3655,29 @@ protected internal virtual void DrawRadioBorder(PdfCanvas canvas, PdfFormXObject
35933655
/// <param name="height">the height of the radio button to draw</param>
35943656
/// <param name="value">the value of the button</param>
35953657
protected internal virtual void DrawRadioAppearance(float width, float height, String value) {
3658+
Rectangle rect = new Rectangle(0, 0, width, height);
3659+
PdfWidgetAnnotation widget = GetWidgets()[0];
3660+
widget.SetNormalAppearance(new PdfDictionary());
3661+
//On state
35963662
PdfStream streamOn = (PdfStream)new PdfStream().MakeIndirect(GetDocument());
35973663
PdfCanvas canvasOn = new PdfCanvas(streamOn, new PdfResources(), GetDocument());
3598-
Rectangle rect = new Rectangle(0, 0, width, height);
35993664
PdfFormXObject xObjectOn = new PdfFormXObject(rect);
3600-
PdfFormXObject xObjectOff = new PdfFormXObject(rect);
36013665
DrawRadioBorder(canvasOn, xObjectOn, width, height);
36023666
DrawRadioField(canvasOn, width, height, true);
3667+
xObjectOn.GetPdfObject().GetOutputStream().WriteBytes(streamOn.GetBytes());
3668+
widget.GetNormalAppearanceObject().Put(new PdfName(value), xObjectOn.GetPdfObject());
3669+
//Off state
36033670
PdfStream streamOff = (PdfStream)new PdfStream().MakeIndirect(GetDocument());
36043671
PdfCanvas canvasOff = new PdfCanvas(streamOff, new PdfResources(), GetDocument());
3672+
PdfFormXObject xObjectOff = new PdfFormXObject(rect);
36053673
DrawRadioBorder(canvasOff, xObjectOff, width, height);
3674+
xObjectOff.GetPdfObject().GetOutputStream().WriteBytes(streamOff.GetBytes());
3675+
widget.GetNormalAppearanceObject().Put(new PdfName("Off"), xObjectOff.GetPdfObject());
36063676
if (pdfAConformanceLevel != null && (pdfAConformanceLevel.GetPart().Equals("2") || pdfAConformanceLevel.GetPart
36073677
().Equals("3"))) {
36083678
xObjectOn.GetResources();
36093679
xObjectOff.GetResources();
36103680
}
3611-
PdfWidgetAnnotation widget = GetWidgets()[0];
3612-
xObjectOn.GetPdfObject().GetOutputStream().WriteBytes(streamOn.GetBytes());
3613-
widget.SetNormalAppearance(new PdfDictionary());
3614-
widget.GetNormalAppearanceObject().Put(new PdfName(value), xObjectOn.GetPdfObject());
3615-
xObjectOff.GetPdfObject().GetOutputStream().WriteBytes(streamOff.GetBytes());
3616-
widget.GetNormalAppearanceObject().Put(new PdfName("Off"), xObjectOff.GetPdfObject());
36173681
}
36183682

36193683
/// <summary>Draws the appearance of a radio button with a specified value.</summary>
@@ -3626,10 +3690,12 @@ protected internal virtual void DrawPdfA1RadioAppearance(float width, float heig
36263690
Rectangle rect = new Rectangle(0, 0, width, height);
36273691
PdfFormXObject xObject = new PdfFormXObject(rect);
36283692
DrawBorder(canvas, xObject, width, height);
3629-
DrawRadioField(canvas, rect.GetWidth(), rect.GetHeight(), !value.Equals("Off"));
3693+
DrawRadioField(canvas, rect.GetWidth(), rect.GetHeight(), !"Off".Equals(value));
3694+
PdfDictionary normalAppearance = new PdfDictionary();
3695+
normalAppearance.Put(new PdfName(value), xObject.GetPdfObject());
36303696
PdfWidgetAnnotation widget = GetWidgets()[0];
36313697
xObject.GetPdfObject().GetOutputStream().WriteBytes(stream.GetBytes());
3632-
widget.SetNormalAppearance(xObject.GetPdfObject());
3698+
widget.SetNormalAppearance(normalAppearance);
36333699
}
36343700

36353701
/// <summary>Draws a radio button.</summary>

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
def5fdf6ef2e257aecb9b6bdbdf83b5f904e817e
1+
0c65942f362e5cd6277352ed566dc911c5ede0fc

0 commit comments

Comments
 (0)