PDFsharp & MigraDoc Foundation
http://forum.pdfsharp.com/

PdfSharp - AcroForm DrawString position in PdfTextField
http://forum.pdfsharp.com/viewtopic.php?f=3&t=3506
Page 1 of 1

Author:  zaryk [ Mon Nov 28, 2016 7:18 am ]
Post subject:  PdfSharp - AcroForm DrawString position in PdfTextField

Keep in mind that the code that I added was for testing, flexibility, and also to use as much code already available as possible. Also, my testing has only been on one AcroForm template. I am also sure that you are working on these areas, so it may be useless to mention:

<package id="PDFsharp-MigraDoc-gdi" version="1.50.4000-beta3b" targetFramework="net45" />

Currently, pdfsharp sets a default of XStringFormat.TopLeft. This was causing issues in textboxes, where the positioning was off between onfocus and non-focus of text because PDFSharp does not take into account of pre-existing alignment, and the margining/padding is different from the adobe. It was also not taking into account word-wrap in a multiline for TopLeft. The below code does not take into account multiline for other alignments, since you currently have it throw an exception, but I may come back with a fix for that as well.

What I ended up doing was adding a property for alignment that looks like this:


Code:
//PdfTextField.cs
        public XStringFormat Alignment
        {
            get {
                XStringFormat _alignment;
                if (MultiLine)
                {
                    _alignment = XStringFormats.TopLeft;

                    switch (Elements.GetInteger(Keys.Q))
                    {
                        case 0:
                            _alignment = XStringFormats.TopLeft;
                            break;
                        case 1:
                            _alignment = XStringFormats.TopCenter;
                            break;
                        case 2:
                            _alignment = XStringFormats.TopRight;
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    _alignment = XStringFormats.CenterLeft;
                    switch (Elements.GetInteger(Keys.Q))
                    {
                        case 0:
                            _alignment = XStringFormats.CenterLeft;
                            break;
                        case 1:
                            _alignment = XStringFormats.Center;
                            break;
                        case 2:
                            _alignment = XStringFormats.CenterRight;
                            break;
                        default:
                            break;
                    }
                }
                return _alignment;
            }
            set {
                    if (XStringFormats.Equals(value, XStringFormats.CenterLeft) || XStringFormats.Equals(value, XStringFormats.BottomLeft) || XStringFormats.Equals(value, XStringFormats.TopLeft))
                    {
                        Elements.SetInteger(Keys.Q, 0);
                    }
                    else if (XStringFormats.Equals(value, XStringFormats.Center) || XStringFormats.Equals(value, XStringFormats.TopCenter) || XStringFormats.Equals(value, XStringFormats.BottomCenter))
                    {
                        Elements.SetInteger(Keys.Q, 1);
                    }
                    else if (XStringFormats.Equals(value, XStringFormats.CenterRight) || XStringFormats.Equals(value, XStringFormats.TopRight) || XStringFormats.Equals(value, XStringFormats.BottomRight))
                    {
                        Elements.SetInteger(Keys.Q, 2);
                    } 
               
            }
        }

        public double TopMargin
        {
            get { return _topMargin; }
            set { _topMargin = value; }
        }
        double _topMargin = 0;

        public double BottomMargin
        {
            get { return _bottomMargin; }
            set { _bottomMargin = value; }
        }
        double _bottomMargin = 0;

        public double LeftMargin
        {
            get { return _leftMargin; }
            set { _leftMargin = value; }
        }
        double _leftMargin = 0;

        public double RightMargin
        {
            get { return _rightMargin; }
            set { _rightMargin = value; }
        }
        double _rightMargin = 0;


I changed the RenderAppearance to the below. This one and the following could be added together so the margin properties would not be needed:
Code:
 //PdfTextField->RenderAppearance

            PdfRectangle rect = Elements.GetRectangle(PdfAnnotation.Keys.Rect);
            XForm form = new XForm(_document, rect.Size);
            XGraphics gfx = XGraphics.FromForm(form);
            XRect xrect = (rect.ToXRect() - rect.Location);

            if (_backColor != XColor.Empty)
                gfx.DrawRectangle(new XSolidBrush(BackColor), xrect);

            string text = Text;
           

            if (text.Length > 0)
            {
               
                xrect.Y = xrect.Y + TopMargin;
                xrect.X = xrect.X + LeftMargin;
                xrect.Width = xrect.Width + RightMargin;
                xrect.Height = xrect.Height + BottomMargin;
                if (this.MultiLine)
                {
                    XTextFormatter formatter = new XTextFormatter(gfx);
                    formatter.Text = text;
                   
                    formatter.DrawString(Text, Font, new XSolidBrush(ForeColor),
                     xrect, Alignment);
                }
                else
                {
                    gfx.DrawString(Text, Font, new XSolidBrush(ForeColor),
                     xrect, Alignment);
                }
            }


Where I am using PdfSharp, I added:
Code:
                    if (textbox.MultiLine)
                    {
                        if (XStringFormats.Equals(textbox.Alignment, XStringFormats.TopLeft))
                        {
                            textbox.LeftMargin = 2;
                            textbox.TopMargin = -6;
                            textbox.RightMargin = 0;
                            textbox.BottomMargin = 0;
                        }
                        else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.TopCenter))
                        {

                        }
                        else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.TopRight))
                        {

                        }

                    }
                    else
                    {
                        if (XStringFormats.Equals(textbox.Alignment, XStringFormats.CenterLeft))
                        {
                           textbox.LeftMargin = 2;
                            textbox.TopMargin = .25;
                            textbox.RightMargin = 0;
                            textbox.BottomMargin = 0;
                        }
                        else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.Center))
                        {
                            textbox.TopMargin = .25;
                        }
                        else if (XStringFormats.Equals(textbox.Alignment, XStringFormats.CenterRight))
                        {
                            textbox.LeftMargin = 0;
                            textbox.TopMargin = .25;
                            textbox.RightMargin = -2;
                            textbox.BottomMargin = 0;

                        }
                    }


I also changed XStringFormats to have an Equals method:
Code:
        public static bool Equals(XStringFormat format1, XStringFormat format2)
        {
            if((format1 == null && format2 == null))
            {
                return true;
            }
            else if((format1 != null && format2 == null) || (format2 != null && format1 == null))
            {
                return false;
            }
            return (format1.Alignment == format2.Alignment && format1.LineAlignment == format2.LineAlignment);
        }

Author:  zaryk [ Mon Nov 28, 2016 4:39 pm ]
Post subject:  Re: PdfSharp - AcroForm DrawString position in PdfTextField

BTW, I am also using everything stated in this post:

viewtopic.php?f=2&t=3504

and also flattening:

Where I am using PDFSharp:
Code:
if (Flatten)
            {
                PdfAcroField.PdfAcroFieldCollection fields = form.Fields;

                string[] names = fields.Names;
                string fqName = null;
                PdfAcroField field = null;
                for (int idx = 0; idx < names.Length; idx++)
                {
                    fqName = names[idx];
                    field = fields[fqName];
                    if (field != null)
                    {
                        field.ReadOnly = true;
                    }
                }
                form.Elements.Remove(PdfAcroForm.Keys.NeedAppearances);

                //pdfSharpDocument.SecuritySettings.PermitAccessibilityExtractContent = true;
                //pdfSharpDocument.SecuritySettings.PermitFullQualityPrint = true;
                //pdfSharpDocument.SecuritySettings.PermitPrint = true;
                //pdfSharpDocument.SecuritySettings.PermitAnnotations = true;
                //pdfSharpDocument.SecuritySettings.PermitExtractContent = true;
                //pdfSharpDocument.SecuritySettings.PermitAssembleDocument = false;
                //pdfSharpDocument.SecuritySettings.PermitFormsFill = false;
                //pdfSharpDocument.SecuritySettings.PermitModifyDocument = true;
            }

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/