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

Notification

Icon
Error

Post a reply
From:
Message:

Maximum number of characters in each post is: 32767
Bold Italic Underline   Highlight Quote Choose Language for Syntax Highlighting Insert Image Insert an existing Attachment or upload a new File... Create Link   Unordered List Ordered List   Left Justify Center Justify Right Justify   Outdent Indent   More BBCode Tags
Font Color Font Size
Security Image:
Enter The Letters From The Security Image:
  Preview Post Cancel

Last 10 Posts (In reverse order)
richard Posted: Monday, July 8, 2019 8:16:01 PM(UTC)
 
Hey Paul,

Looks like Document.Root Acroform DR does have a font entry with "Helv". Should be able to use that with your algorithm.

Thanks a lot!

Richard
Paul Rayman Posted: Friday, July 5, 2019 11:02:17 PM(UTC)
 
Do you mean the dictionary key DA?

The DA is the default appearance string containing a sequence of valid page-content graphics or text state operators that define such properties as the field’s text size and color.

You can try to parse the DA string using Pdfium.FPDFTOOLS_ParseDefaultAppearance(...).
Then create the font using the PdfFont.CreateStandardFont(doc, fontName, 1), where fontName is a string representation of the standard font.
The CreateStandardFont method can only parse the following font names, so I think "/Helv 10 Tf 0 g" is either a mistakenly formed font name, or is a reference to the font in the "DR" entry or in the page’s resource dictionary. Try to explore each of them: document.Root["AcroForm"]->"DR"->"Font", page.Dictionary["Resources"]->"Font", ctrl.Dictionary["DR"], perhaps there is a key named Helv, which contains the actual font, an instance of which can be created through a call of PdfFont.CreateFont(document, fontDictionary) method. Where fontDictionary is a font dictionary contained under Helv key as direct or indirect object.


The valid names for standard fonts are:
Quote:
{"Arial", 4},
{"Arial,Bold", 5},
{"Arial,BoldItalic", 6},
{"Arial,Italic", 7},
{"Arial-Bold", 5},
{"Arial-BoldItalic", 6},
{"Arial-BoldItalicMT", 6},
{"Arial-BoldMT", 5},
{"Arial-Italic", 7},
{"Arial-ItalicMT", 7},
{"ArialBold", 5},
{"ArialBoldItalic", 6},
{"ArialItalic", 7},
{"ArialMT", 4},
{"ArialMT,Bold", 5},
{"ArialMT,BoldItalic", 6},
{"ArialMT,Italic", 7},
{"ArialRoundedMTBold", 5},
{"Courier", 0},
{"Courier,Bold", 1},
{"Courier,BoldItalic", 2},
{"Courier,Italic", 3},
{"Courier-Bold", 1},
{"Courier-BoldOblique", 2},
{"Courier-Oblique", 3},
{"CourierBold", 1},
{"CourierBoldItalic", 2},
{"CourierItalic", 3},
{"CourierNew", 0},
{"CourierNew,Bold", 1},
{"CourierNew,BoldItalic", 2},
{"CourierNew,Italic", 3},
{"CourierNew-Bold", 1},
{"CourierNew-BoldItalic", 2},
{"CourierNew-Italic", 3},
{"CourierNewBold", 1},
{"CourierNewBoldItalic", 2},
{"CourierNewItalic", 3},
{"CourierNewPS-BoldItalicMT", 2},
{"CourierNewPS-BoldMT", 1},
{"CourierNewPS-ItalicMT", 3},
{"CourierNewPSMT", 0},
{"CourierStd", 0},
{"CourierStd-Bold", 1},
{"CourierStd-BoldOblique", 2},
{"CourierStd-Oblique", 3},
{"Helvetica", 4},
{"Helvetica,Bold", 5},
{"Helvetica,BoldItalic", 6},
{"Helvetica,Italic", 7},
{"Helvetica-Bold", 5},
{"Helvetica-BoldItalic", 6},
{"Helvetica-BoldOblique", 6},
{"Helvetica-Italic", 7},
{"Helvetica-Oblique", 7},
{"HelveticaBold", 5},
{"HelveticaBoldItalic", 6},
{"HelveticaItalic", 7},
{"Symbol", 12},
{"SymbolMT", 12},
{"Times-Bold", 9},
{"Times-BoldItalic", 10},
{"Times-Italic", 11},
{"Times-Roman", 8},
{"TimesBold", 9},
{"TimesBoldItalic", 10},
{"TimesItalic", 11},
{"TimesNewRoman", 8},
{"TimesNewRoman,Bold", 9},
{"TimesNewRoman,BoldItalic", 10},
{"TimesNewRoman,Italic", 11},
{"TimesNewRoman-Bold", 9},
{"TimesNewRoman-BoldItalic", 10},
{"TimesNewRoman-Italic", 11},
{"TimesNewRomanBold", 9},
{"TimesNewRomanBoldItalic", 10},
{"TimesNewRomanItalic", 11},
{"TimesNewRomanPS", 8},
{"TimesNewRomanPS-Bold", 9},
{"TimesNewRomanPS-BoldItalic", 10},
{"TimesNewRomanPS-BoldItalicMT", 10},
{"TimesNewRomanPS-BoldMT", 9},
{"TimesNewRomanPS-Italic", 11},
{"TimesNewRomanPS-ItalicMT", 11},
{"TimesNewRomanPSMT", 8},
{"TimesNewRomanPSMT,Bold", 9},
{"TimesNewRomanPSMT,BoldItalic", 10},
{"TimesNewRomanPSMT,Italic", 11},
{"ZapfDingbats", 13},


So the algorithm is:
1. Parse Default Appearance (DA) and get fontName (using FPDFTOOL_ParseDefaultAppearance);
2. Check if fontName is a standard name;
2.1. if so - Use CreateStandardFont;

3. find font dictionary under fontName entry in
3.1. document.Root -> AcroForm -> DR
3.2 "DR" entry in ctrl.Dictionary
3.3 page.Dictionary -> Resources -> Font
(i'm not sure about 3.2 and 3.3 - perhaps this is unnecessary actions)
4. if found - create font using CreateFont
5. if not found - DA is broken;


You can still use annotations instead.
Perhaps your task can be solved as follows.
Code:
public float GetStringWidth(PdfControl ctrl, string text, PdfPage page)
{
    if (ctrl == null || page == null || string.IsNullOrEmpty(text))
        return 0;

    string oldText = ctrl.Field.Value;
    try
    {
        ctrl.Field.Value = text;
        using (var ann = PdfAnnotation.Create(ctrl.Dictionary, page))
        {
            if(ann.NormalAppearance.Count>0)
                return ann.NormalAppearance[0].BoundingBox.Width;
            else
                return 0;
        }
    }
    finally
    {
        ctrl.Field.Value = oldText;
    }
}


Code:
using (var document = PdfDocument.Load(@"e:\9\test.pdf", new PdfForms()))
{
    var ctrl = document.FormFill.InterForm.Controls[0];
    var page = document.Pages[0]; //https://forum.patagames.com/posts/t559-Return-the-Page-a-Field-is-On

    float width = GetStringWidth(ctrl, "t1", page);
    width = GetStringWidth(ctrl, "MMM", page);
    width = GetStringWidth(ctrl, "qwerty", page);


}
richard Posted: Thursday, July 4, 2019 6:18:10 AM(UTC)
 
Hi Paul,

I'd like to use the first method you mentioned, but as I said in my last reply it's a bit of a bother to go from "Helv" to FontStockNames.Helvetica when creating a font (or whatever other font a control might happen to have). Is there a way to get a PdfFont from an existing control which (seemingly) only has the "/Helv 10 Tf 0 g" dictionary item?

Regards,

Richard
richard Posted: Tuesday, July 2, 2019 11:15:12 PM(UTC)
 
Hi Paul,

Thanks again for the always excellent help!

FYI the first two methods give the exact same width result while the third one is always +1.5 bigger. Also getting from "Helv" to FontStockNames.Helvetica for the third method is a bit fraught. Think I'll stick with the annots method.

Regards,

Richard
Paul Rayman Posted: Tuesday, July 2, 2019 7:28:50 AM(UTC)
 
Try the following

Code:
PdfTextObject tempTextObj = PdfTextObject.Create(text, 0, 0, font, fontSize);
var width = tempTextObj.BoundingBox.Width;


Also, if the text is already contained in the control, you can try the following.
In fact, the control is a widget annotation. Thus, you can convert it to an annotation and get all the text objects from its normal appearance stream.

Code:
PdfWidgetAnnotation annot = new PdfWidgetAnnotation(page, ctrl.Dictionary);
foreach( var obj in annot.NormalAppearance)
{
    if (!(obj is PdfTextObject))
        continue;
    var width = obj.BoundingBox.Width;
}


Originally Posted by: richard Go to Quoted Post
"/Helv 10 Tf 0 g"

Also the following should work
Code:
string text = "abcdefg";
float fontSize = 10.0f;
PdfFont font = PdfFont.CreateStock(doc, FontStockNames.Helvetica);
var width = font.GetStringWidth(text) / 1000.0f * fontSize;
richard Posted: Tuesday, July 2, 2019 7:00:09 AM(UTC)
 
Just reading that again and realised the code was getting/using a default font. Is there a way to use these methods (or similar) with the actual font of the control?
richard Posted: Tuesday, July 2, 2019 6:58:25 AM(UTC)
 
Hello,

I'm trying to get the width of the text in a textbox in order to compare it with the width of the textbox itself. I've found the various methods for getting fonts and string widths but haven't had much luck with them (most certainly I'm missing something). Here's a sample of code I've played around with:

Code:

if (Document.SelectedField is PdfFieldViewModel fld)
{
   PdfControl ctrl = fld.Field.Controls.FirstOrDefault();

   if (ctrl != null)
   {
      var text = "MMMMMMMMMM";
      var font = Pdfium.FPDFFormControl_GetDefaultControlFont(ctrl.Handle);
      var fontName = Pdfium.FPDFFont_GetFontTypeName(font);
      var textWidth = Pdfium.FPDFFont_GetStringWidth(font, text);
   }
}


The control in question 132.93 wide and has a font (in its Dictionary) of "/Helv 10 Tf 0 g". However the fontName from the above code evaluates as "Type1" and the textWidth of the text string (which just fills the textbox) as 8330.

I've also tried the PDFFont.GetStringWidth() method with similar results.

Am I going about this the wrong way? Or is there some step I'm missing? Font size doesn't seem to come into the equation with these string width methods, maybe I need a conversion for the width values I'm getting?

Thanks a lot!

Richard