logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
richard  
#1 Posted : Monday, July 15, 2019 4:28:39 AM(UTC)
richard

Rank: Member

Groups: Registered
Joined: 5/9/2019(UTC)
Posts: 16
Australia
Location: Sydney

Hi Paul,

I'm trying to update the font size of a text field by changing the DA dictionary entry both while the user is typing and through a button/context menu. I've got a much simplified and contrived sample project here which gives the basic idea of what I'm trying to achieve. You can use b.pdf (3kb) downloaded 2 time(s). to test.

When the user is typing I basically want to force remove focus in order to update the control value, so I know what they've typed, analyse the width and if necessary update the Dictionary to the new font size. I then want to click back into the control to (ideally) update the text to the new font size.

If you try with my sample project/pdf and type a single extra letter in the text field you should see the font size update correctly, but if you then click out of the control it reverts to the previous size. Clicking in and out repeatedly will continue to alternate the size. Likewise if you use the shrink text button at the top (which tries essentially the same code).

I've tried various redrawings/invalidations/etc of the page, FixPageFields(), GenerateContent() etc, but feel that's all on the wrong track. When I debug and examine the data it seems that the font size for the control in Document.FormFill.InterForm.Controls[0].Dictionary and Document.Pages.Annots[0].Dictionary is updated, but the FontSize property in Document.Pages.Annots[0].NormalAppearance remains the old value.

Any ideas how I can force the new font size to display permanently?

Many thanks,

Richard

Edited by user Monday, July 15, 2019 4:29:31 AM(UTC)  | Reason: Not specified

Paul Rayman  
#2 Posted : Monday, July 15, 2019 11:14:12 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 779

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
My guesses about this:
1. In addition to the NormalAppearance, there is also DownAppearance and RolloverAppearance. Check them too. However, due to the fact that many viewers ignore these values, I think they are not used. But ... just in case.
2. NormalAppearance is displayed only when the field has no focus. If the field has focus, then it is rendered by the engine based on the settings specified in the DA entry. You can ensure this if you create NormalAppearance, with settings different from those specified in the DA entry.
4. When the forum loses focus, the engine re-creates the NormalAppearance based on the settings in the DA. But... I am not 100% sure about this. If not, try deleting the NormalAppearance so that the engine re-creates it.
5. The engine parses and caches the settings in the DA when the page loads, so you have to reload the page.

Try at the moment when you change the DA call page.Dispose(). This will force the page to reload. Don't wory about it. The SDK architecture is such that pages are not load immediately. Loading is unexplicit at first use. Therefore, if you dispose the page, then at the next use, it will be immediately loaded and ... this time ... new values ​​from the DA entry will be applied I hope.
richard  
#3 Posted : Tuesday, July 16, 2019 11:11:11 AM(UTC)
richard

Rank: Member

Groups: Registered
Joined: 5/9/2019(UTC)
Posts: 16
Australia
Location: Sydney

Hi Paul,

Thanks for the suggestions. It didn't quite work but I think I'm on the right track and nearly there. I'm unable to delete the NormalAppearance so I first tried just clearing it.

Code:
Document.Pages[0].Annots[0].NormalAppearance.Clear();


I also tried setting the font explicitly.

Code:
var textAnnots = Document.Pages[0].Annots[0].NormalAppearance.OfType<PdfTextObject>();

foreach (var textObject in textAnnots)
{
   textObject.FontSize = 5f;
}


After each of these when I called page.Dispose() it would recreate the NormalAppearance but still using the old incorrect font size. I then found the N entry in the PdfAnnotation's AP dictionary, which contains the font size for the normal appearance. I tried changing that explicitly with the following code.

Code:
Document.Pages[0].Annots[0].NormalAppearance.Clear();

var annot = Document.Pages[0].Annots[0];
var pdfTypeDictionary = annot.Dictionary["AP"] as PdfTypeDictionary;
var pdfTypeIndirect = pdfTypeDictionary["N"] as PdfTypeIndirect;
var pdfTypeStream = pdfTypeIndirect.Direct as PdfTypeStream;
var decodedText = pdfTypeStream.DecodedText;

var alteredText = decodedText.Replace("/Helv 18 Tf", "/Helv 5 Tf");

var alteredTextByteArray = PdfCommon.DefaultAnsiEncoding.GetBytes(alteredText);

pdfTypeStream.SetContent(alteredTextByteArray, true);

page.Dispose();


This works, with only one problem. The re-created NormalAppearance PdfTextObject now has different BoundingBox coordinates, meaning it is rendered slightly lower in the text control.

Do you think this is an acceptable solution and any idea why that last BoundingBox problem might be happening?

Regards,

Richard
Paul Rayman  
#4 Posted : Tuesday, July 16, 2019 12:40:04 PM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 779

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
Hm....

Please look at this document test.pdf_decoded.pdf (6kb) downloaded 1 time(s).
I assume that the form field is already working as you need.

This feature has already been implemented and is called “automatic font size”.

Just set font size to 0 in the DA entry.

Please look inside test.pdf_decoded.pdf (using notepad)
Untitled.png (42kb) downloaded 2 time(s).
richard  
#5 Posted : Tuesday, July 16, 2019 7:42:33 PM(UTC)
richard

Rank: Member

Groups: Registered
Joined: 5/9/2019(UTC)
Posts: 16
Australia
Location: Sydney

Thanks Paul.

I'm aware of the 0 font size but unfortunately I'm unable to use it for one or two reasons.

Richard
Paul Rayman  
#6 Posted : Tuesday, July 16, 2019 9:58:14 PM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 779

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
Code:
Document.Pages[0].Annots[0].NormalAppearance.Clear();


Try removing the "N" entry from the dictionary instead

Edited by user Tuesday, July 16, 2019 10:00:38 PM(UTC)  | Reason: Not specified

richard  
#7 Posted : Wednesday, July 17, 2019 4:37:23 AM(UTC)
richard

Rank: Member

Groups: Registered
Joined: 5/9/2019(UTC)
Posts: 16
Australia
Location: Sydney

Doesn't work I'm afraid. When the "N" entry is regenerated it's blank, so the control disappears when you lose focus.

I've found a hacky workaround, which I'll put here in case any one else faces this problem. If you enter another character then the "N" appearance stream will be updated with the new font size, so I pretty much enter a random character, remove focus, click back at the same place then press backspace.

Code:
var page = pdfViewer.Document.Pages[pdfViewer.CurrentIndex];
var control = pdfViewer.Document.FormFill.InterForm.Controls[0];

var originalText = control.Field.Value;

if (control.Dictionary["DA"] is PdfTypeString pdfTypeString)
{
    var parts = pdfTypeString.AnsiString.Split(new[] { " " }, StringSplitOptions.None);
    parts[1] = "5";
    var str = string.Join(" ", parts);

    pdfTypeString.AnsiString = str;
    control.Dictionary["DA"] = pdfTypeString;
}

var clickPoint = new PointF(control.BoundRect.left + control.BoundRect.Width - 1, control.BoundRect.bottom + 5);
ForceClickMouseOnDocumentAt(page, clickPoint);

page.OnKeyDown(FWL_VKEYCODE.FWL_VKEY_Space, 0);
page.OnKeyUp(FWL_VKEYCODE.FWL_VKEY_Space, 0);

pdfViewer.Document.FormFill.ForceToKillFocus();
ForceClickMouseOnDocumentAt(page, clickPoint);

// If the text field is full then the spacebar press above will not
// have been added to the field's string value, so don't backspace
if (control.Field.Value != originalText)
{
    page.OnKeyDown(FWL_VKEYCODE.FWL_VKEY_Back, 0);
    page.OnKeyUp(FWL_VKEYCODE.FWL_VKEY_Back, 0);
}

pdfViewer.Document.FormFill.ForceToKillFocus();
ForceClickMouseOnDocumentAt(page, clickPoint);


As I said, pretty hacky, but isn't noticeable and seems to work fine!
Paul Rayman  
#8 Posted : Wednesday, July 17, 2019 7:04:43 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 779

Thanks: 1 times
Was thanked: 97 time(s) in 95 post(s)
Maybe I do not clearly understand your task, but I prepare such example on this document test.pdf (4kb) downloaded 1 time(s). with only following code

Code:
private void ChangeFontSizeOfField()
{
    var ctrl = pdfViewer1.Document.FormFill.InterForm.Controls[0];
    var field = ctrl.Field;
    _size = _size < 18 ? _size + 2 : 0;

    string da = $"/TiBo {_size} Tf 0.25098 0.12549 0 rg";
    field.Dictionary["DA"] = PdfTypeString.Create(da);
    field.Dictionary.Remove("AP");
    pdfViewer1.Document.Pages[0].Dispose();
    pdfViewer1.Invalidate();


    this.toolStripLabel2.Text = _size.ToString();
}


and illustration how it works. Hope it helps you:

Edited by user Wednesday, July 17, 2019 7:05:41 AM(UTC)  | Reason: Not specified

richard  
#9 Posted : Wednesday, July 17, 2019 10:20:29 AM(UTC)
richard

Rank: Member

Groups: Registered
Joined: 5/9/2019(UTC)
Posts: 16
Australia
Location: Sydney

Looks like you got it! Much cleaner solution and seems to work fine.

Thanks a lot!
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.