Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions annotator/field_appearance.go
Original file line number Diff line number Diff line change
Expand Up @@ -821,18 +821,21 @@ func genFieldComboboxAppearance(form *model.PdfAcroForm, wa *model.PdfAnnotation
}
}

// See section 12.7.4.4 "Choice Fields" (pp. 444-446 PDF32000_2008).
dchoiceapp := core.MakeDict()
for _, optObj := range fch.Opt.Elements() {
if optArr, ok := core.GetArray(optObj); ok && optArr.Len() == 2 {
optObj = optArr.Get(1)
}

var optstr string
if opt, ok := core.GetString(optObj); ok {
optstr = opt.Decoded()
} else if opt, ok := core.GetName(optObj); ok {
optstr = opt.String()
} else {
if opt, ok := core.GetName(optObj); ok {
optstr = opt.String()
} else {
common.Log.Debug("ERROR: Opt not a name/string - %T", optObj)
return nil, errors.New("not a name/string")
}
common.Log.Debug("ERROR: Opt not a name/string - %T", optObj)
return nil, errors.New("not a name/string")
}

if len(optstr) > 0 {
Expand Down
43 changes: 43 additions & 0 deletions fjson/fielddata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func TestJSONExtractAndFill(t *testing.T) {
fieldDataExp, err := LoadFromJSONFile("./testdata/advancedform.json")
require.NoError(t, err)
jsonDataExp, err := fieldDataExp.JSON()
require.NoError(t, err)

// Check templates for equality.
require.Equal(t, jsonDataExp, jsonData)
Expand Down Expand Up @@ -184,6 +185,7 @@ func TestJSONExtractAndFill(t *testing.T) {
fieldDataExp, err = LoadFromJSON(bytes.NewReader(jsonBytes))
require.NoError(t, err)
jsonDataExp, err = fieldDataExp.JSON()
require.NoError(t, err)

// Fill test PDF form fields and write to buffer.
f, err := os.Open(inputFilePath)
Expand Down Expand Up @@ -212,6 +214,47 @@ func TestJSONExtractAndFill(t *testing.T) {
fieldData, err = LoadFromPDF(bytes.NewReader(buf.Bytes()))
require.NoError(t, err)
jsonData, err = fieldData.JSON()
require.NoError(t, err)

// Check field data for equality.
require.Equal(t, jsonDataExp, jsonData)
}

func TestJSONFillAndExtract(t *testing.T) {
// Read JSON fill data.
fieldDataExp, err := LoadFromJSONFile("./testdata/mixedfields.json")
require.NoError(t, err)
jsonDataExp, err := fieldDataExp.JSON()
require.NoError(t, err)

// Fill test PDF form fields and write to buffer.
f, err := os.Open("./testdata/mixedfields.pdf")
require.NoError(t, err)
defer f.Close()

reader, err := model.NewPdfReader(f)
require.NoError(t, err)

err = reader.AcroForm.Fill(fieldDataExp)
require.NoError(t, err)

var buf bytes.Buffer
writer := model.NewPdfWriter()
for i := range reader.PageList {
err := writer.AddPage(reader.PageList[i])
require.NoError(t, err)
}

err = writer.SetForms(reader.AcroForm)
require.NoError(t, err)
err = writer.Write(&buf)
require.NoError(t, err)

// Load field data from buffer.
fieldData, err := LoadFromPDF(bytes.NewReader(buf.Bytes()))
require.NoError(t, err)
jsonData, err := fieldData.JSON()
require.NoError(t, err)

// Check field data for equality.
require.Equal(t, jsonDataExp, jsonData)
Expand Down
94 changes: 94 additions & 0 deletions fjson/testdata/mixedfields.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
[
{
"name": "Given Name Text Box",
"value": "Jane"
},
{
"name": "Family Name Text Box",
"value": "Doe"
},
{
"name": "House nr Text Box",
"value": "100"
},
{
"name": "Address 2 Text Box",
"value": "Generic Avenue"
},
{
"name": "Postcode Text Box",
"value": "11122"
},
{
"name": "Country Combo Box",
"value": "France"
},
{
"name": "Height Formatted Field",
"value": "175"
},
{
"name": "City Text Box",
"value": "Paris"
},
{
"name": "Driving License Check Box",
"value": "Yes",
"options": [
"Yes",
"Off"
]
},
{
"name": "Favourite Colour List Box",
"value": "Yellow"
},
{
"name": "Language 1 Check Box",
"value": "Yes",
"options": [
"Yes",
"Off"
]
},
{
"name": "Language 2 Check Box",
"value": "Off",
"options": [
"Yes",
"Off"
]
},
{
"name": "Language 3 Check Box",
"value": "Yes",
"options": [
"Yes",
"Off"
]
},
{
"name": "Language 4 Check Box",
"value": "Off",
"options": [
"Yes",
"Off"
]
},
{
"name": "Language 5 Check Box",
"value": "Yes",
"options": [
"Yes",
"Off"
]
},
{
"name": "Gender List Box",
"value": "Woman"
},
{
"name": "Address 1 Text Box",
"value": "Generic Street"
}
]
Binary file added fjson/testdata/mixedfields.pdf
Binary file not shown.
7 changes: 4 additions & 3 deletions model/flatten.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ func (r *PdfReader) FlattenFields(allannots bool, appgen FieldAppearanceGenerato
var annots []*PdfAnnotation

// Wrap the content streams.
err := appgen.WrapContentStream(page)
if err != nil {
return err
if appgen != nil {
if err := appgen.WrapContentStream(page); err != nil {
return err
}
}

annotations, err := page.GetAnnotations()
Expand Down
46 changes: 32 additions & 14 deletions model/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,26 +317,36 @@ func fillFieldValue(f *PdfField, val core.PdfObject) error {
default:
common.Log.Debug("ERROR: Unsupported text field V type: %T (%#v)", t, t)
}
case *PdfFieldButton, *PdfFieldChoice:
switch t := val.(type) {
case *PdfFieldButton:
// See section 12.7.4.2.3 "Check Boxes" (pp. 440-441 PDF32000_2008).
switch val.(type) {
case *core.PdfObjectName:
if len(t.String()) == 0 {
return nil
if len(val.String()) > 0 {
f.V = val
setFieldAnnotAS(f, val)
}
for _, wa := range f.Annotations {
wa.AS = val
case *core.PdfObjectString:
if len(val.String()) > 0 {
f.V = core.MakeName(val.String())
setFieldAnnotAS(f, f.V)
}
default:
common.Log.Debug("ERROR: UNEXPECTED %s -> %v", f.PartialName(), val)
f.V = val
case *core.PdfObjectString:
if len(t.String()) == 0 {
return nil
}
case *PdfFieldChoice:
// See section 12.7.4.4 "Choice Fields" (pp. 444-446 PDF32000_2008).
switch val.(type) {
case *core.PdfObjectName:
if len(val.String()) > 0 {
f.V = core.MakeString(val.String())
setFieldAnnotAS(f, val)
}
common.Log.Debug("Unexpected string for button/choice field. Converting to name: '%s'", t.String())
name := core.MakeName(t.String())
for _, wa := range f.Annotations {
wa.AS = name
case *core.PdfObjectString:
if len(val.String()) > 0 {
f.V = val
setFieldAnnotAS(f, core.MakeName(val.String()))
}
f.V = name
default:
common.Log.Debug("ERROR: UNEXPECTED %s -> %v", f.PartialName(), val)
f.V = val
Expand All @@ -347,3 +357,11 @@ func fillFieldValue(f *PdfField, val core.PdfObject) error {

return nil
}

// setFieldAnnotAS sets the appearance stream of the field annotations to `val`.
func setFieldAnnotAS(f *PdfField, val core.PdfObject) {
for _, wa := range f.Annotations {
wa.AS = val
wa.ToPdfObject()
}
}