Hopding / pdf-lib

Create and modify PDF documents in any JavaScript environment
https://pdf-lib.js.org
MIT License
6.97k stars 671 forks source link

setText method removes border & combing #1077

Open krzyswiatkowski opened 3 years ago

krzyswiatkowski commented 3 years ago

What were you trying to do?

Trying to use pdfTextField.setText method to fill pdf-form-field and leave combing & border visible

I have PDF file with prepared form in it. Most of text-fields in this PDF-file has combing & border visible. I want to fill those fields using setText method and leave combing & border visible.

Why were you trying to do this?

I want to fill fields inside pdf-form and leave combing & border visible (border-boxes for letters).

How did you attempt to do it?

Example of how I'm filling the field and how I've tried to restore combing &border after calling setText:

const pdfDoc = await PDFDocument.load(fileBuffer); // fileBuffer loaded before
const myFontBytes = await someUtils.getBytes('myfont.ttf')...  // returning font-file buffer from utility function

pdfDoc.registerFontkit(fontkit);
const font = await this.pdfDoc.embedFont(myFontBytes);

const pdfForm = pdfDoc.getForm();
const textField = pdfForm.getTextField('name');

textField.setText('SomeRandomName');

const [ widget ]= textField.acroField.getWidgets();
widget.getOrCreateBorderStyle().setWidth(1); // trying to restore border
textField.enableCombing(); // trying to restore combing
textField.updateAppearances(font); // trying to force update appearance

pdfForm.updateFieldAppearances(this.font);
pdfForm.flatten({ updateFieldAppearances: true });

const updatedBytes = await this.pdfDoc.save();
await saveToFile(updatedBytes) // utility function

What actually happened?

After using setText method, particular field loses combing & border. setting additonal border doesn't help. calling enableCombing doesn't help.

What did you expect to happen?

after using setText combing with border are still present particular field.

How can we reproduce the issue?

  1. Create simple PDF-form with atleast 1 text field with enabled combing & border
  2. Try to load it with pdf-lib and fill the field with setText method
  3. Save filled pdf-form to new file
  4. open file and check if form-field is populated and combing+border for that field remains

Version

1.17.0

What environment are you running pdf-lib in?

Node

Required Reading

Additional Notes

No response

Hopding commented 3 years ago

Would you please share a file that can be used to reproduce the issue?

krzyswiatkowski commented 3 years ago

Hey @Hopding sorry for delayed response. I'm attaching ZIP archive with 5 files in it:

reproduce-files.zip

So it looks like not the setText method is responsible for removing the border of combed fields - flatten method is.

Edit: Versions of the packages I've used:

pdf-lib: 1.17.0
@pdf-lib/fontkit: 1.1.1
node: v14.15.5
npm: 6.14.11
dcsline commented 3 years ago

I have tested your shown example - it's worked. Here my example code.

const {PDFDocument} = require('pdf-lib');
const fontkit = require('@pdf-lib/fontkit');
const fs = require('fs');
const ubuntuFontBytes = fs.readFileSync('ubuntu-font.ttf');

async function runTest() {  
  var templ= 'example-single-field.pdf';
  const pdfDoc = await PDFDocument.load(fs.readFileSync(templ)); 
  pdfDoc.registerFontkit(fontkit);
  const font = await pdfDoc.embedFont(ubuntuFontBytes);
  const form = pdfDoc.getForm();
  const combedField = form.getTextField('combedField');
  //console.log('Text field contents:', combedField.getText);
  //if (combedField.isCombed()) console.log('Combing is enabled');
  combedField.setText('Filled by script');
  //console.log("-2-" +combedField.isCombed());
  const [ widget ]= combedField.acroField.getWidgets();
  //console.log("W:::"+widget.getOrCreateBorderStyle);
  widget.getOrCreateBorderStyle().setWidth(1); // trying to restore border
  combedField.enableCombing(); // trying to restore combing
  combedField.updateAppearances(font); // trying to force update appearance
  form.updateFieldAppearances(this.font);
  form.flatten({ updateFieldAppearances: true });
  const fillpdfBytes = await pdfDoc.save({ useObjectStreams: true });
  fs.writeFileSync('test.pdf', fillpdfBytes);  //await pdfDoc.save());
}

runTest();
Hopding commented 2 years ago

@krzyswiatkowski thanks for sharing the files! I'll dig into this when I get a chance 👍