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

Notification

Icon
Error

Options
Go to last post Go to first unread
Terry  
#1 Posted : Monday, August 6, 2018 4:11:53 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Hi,

I'm pleased to see that the latest version of Pdfium (3.34.2704) contains new API to add embedded fonts, about which I would be grateful for some extra information.

First, can I add a subsetted TrueType font to a PDF?

Second, if I have a Unicode-based TrueType font file (called, say, 'fontfile.ttf') installed in the Windows fonts directory ('C:\Windows\Fonts'), how can I embed a subset of this font in order to display the contents of a C# Unicode string (say, 'string displayTxt;') in the PDF? A code snippet illustrating how to use the new API would be very useful.

Many thanks for your help.

Terry.
Paul Rayman  
#2 Posted : Monday, August 6, 2018 10:32:48 PM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 10 times
Was thanked: 133 time(s) in 130 post(s)
My understanding is that you can pass the entire of TTF file as byte array to the PdfFont.CreateEmbeddedFont.
For example to embed the font called calist with Bold Italic face you may pass content of calistBI.ttf file

Code:
            var doc = pdfViewer1.Document;
            byte[] fontData = System.IO.File.ReadAllBytes(@"c:\windows\fonts\CALISTBI.TTF");
            PdfFont font = PdfFont.CreateEmbeddedFont(doc, fontData, FontCharSet.ANSI_CHARSET, false);

            var txt = PdfTextObject.Create("This is a test string", 10, 480, font, 13);
            pdfViewer1.CurrentPage.PageObjects.Add(txt);

            pdfViewer1.ClearRenderBuffer();
            pdfViewer1.Invalidate();


The second point of my understanding is that OpenType PS fonts (.OTF) may be used as well.
For example the following code is valid too
Code:
            byte[] fontData = System.IO.File.ReadAllBytes(@"d:\0\11\Pecita.otf");
            PdfFont font = PdfFont.CreateEmbeddedFont(doc, fontData, FontCharSet.ANSI_CHARSET, false);


But if you want to embed only a certain subset of characters from an existing TrueType/OpenType font, you need to extract the appropriate data from the ttf / otf file yourself.

Edited by user Monday, August 6, 2018 11:29:50 PM(UTC)  | Reason: Not specified

Terry  
#3 Posted : Thursday, August 9, 2018 8:53:41 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Hi Paul,

Many thanks for your reply.

It would be useful if Pdfium itself created the font subset (since it is quite complicated), however I understand that .NET provides some help for doing this, which I am currently investigating. I'll let you know how I get on, or if I have any further questions!

Regards,
Terry.
Terry  
#4 Posted : Monday, August 13, 2018 9:09:23 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Hi Paul,

Can you please explain how to embed a font with the 'Identity-H' encoding? I have played around with the 'FontCharSet' parameter of method 'CreateEmbeddedFont', but none of the available values seems appropriate when I want to display in the PDF a totally generic C# Unicode string using a Unicode-based TrueType font that is capable of displaying a wide range of non-Ansi glyphs from many different non-Latin languages.

(In such cases, other PDF libraries I have used created a font dictionary with 'Encoding' value 'Identity-H', 'Subtype' value 'Type0', a 'ToUnicode' stream link, and a 'DescendantFonts' array containing a font dictionary of type 'CIDFontType0' or 'CIDFontType2' and with keys 'CIDSystemInfo', 'FontDescriptor', etc.)

Thanks for your help.

Terry.
Terry  
#5 Posted : Tuesday, August 14, 2018 2:08:27 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Paul, as a concrete example, how should I embed a Unicode font, say 'Arial Unicode MS', to display a C# string containing both Russian and Japanese, say "версия - 署名理由"? Thanks.

Edited by user Tuesday, August 14, 2018 2:09:20 AM(UTC)  | Reason: Not specified

Paul Rayman  
#6 Posted : Tuesday, August 14, 2018 2:16:14 AM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 10 times
Was thanked: 133 time(s) in 130 post(s)
In this case you should create two separate text objects with different fonts.
Paul Rayman  
#7 Posted : Tuesday, August 14, 2018 2:21:05 AM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 10 times
Was thanked: 133 time(s) in 130 post(s)
I have following example

Code:
            int fontType = 1;//  0 - windows, 1 - crossplatform, 2 - embedded
            var doc = pdfViewer1.Document;
            float y = 480;
            byte[] fontData = System.IO.File.ReadAllBytes(@"c:\windows\fonts\ARIALUNI.TTF");
            for (int i = 0; i < 14; i++)
            {
                FontCharSet ch = FontCharSet.DEFAULT_CHARSET;
                string text = "";
                switch (i)
                {
                    case 0: ch = FontCharSet.HANGEUL_CHARSET; text = "이것은 한국어 텍스트입니다."; break; 
                    case 1: ch = FontCharSet.SHIFTJIS_CHARSET; text = "これは韓国語のテキストです"; break;
                    case 2: ch = FontCharSet.HEBREW_CHARSET; text = "זהו טקסט קוריאני"; break;
                    case 3: ch = FontCharSet.ARABIC_CHARSET; text = "هذا هو النص الكوري"; break;
                    case 4: ch = FontCharSet.CHINESEBIG5_CHARSET; text = "這是韓文"; break;
                    case 5: ch = FontCharSet.GB2312_CHARSET; text = "这是韩文"; break;
                    case 6: ch = FontCharSet.RUSSIAN_CHARSET; text = "Это русский текст"; break;
                    case 7: ch = FontCharSet.ANSI_CHARSET; text = "This is a test string"; break;
                    case 8: ch = FontCharSet.BALTIC_CHARSET; text = "Vienkārša testa līnija"; break;
                    case 9: ch = FontCharSet.EASTEUROPE_CHARSET; text = "Jednoduchá zkušební linka"; break;
                    case 10: ch = FontCharSet.GREEK_CHARSET; text = "Απλή γραμμή δοκιμής"; break; 
                    case 11: ch = FontCharSet.THAI_CHARSET; text = "สายทดสอบง่าย"; break;
                    case 12: ch = FontCharSet.TURKISH_CHARSET; text = "Basit test hattı"; break;
                    case 13: ch = FontCharSet.VIETNAMESE_CHARSET; text = "Kiểm tra đơn giản"; break;
                }

                PdfFont font;
                LOGFONT lf = new LOGFONT() { lfFaceName = "Arial Unicode MS", lfCharSet = ch, lfPitchAndFamily = LOGFONT.FontPitchAndFamily.DEFAULT_PITCH | LOGFONT.FontPitchAndFamily.FF_ROMAN, lfWeight = FontWeight.FW_NORMAL };
                if (fontType == 0)
                    font = PdfFont.CreateWindowsFont(doc, lf, false, false);
                else if (fontType == 2)
                    font = PdfFont.CreateEmbeddedFont(doc, fontData, ch, false);
                else
                    font = PdfFont.CreateFont(doc, lf.lfFaceName, true, 0, lf.lfWeight, 0, lf.lfCharSet, false);

                var txt = PdfTextObject.Create(text, 10, y, font, 13);
                pdfViewer1.CurrentPage.PageObjects.Add(txt);
                y -= 30;
            }
            pdfViewer1.ClearRenderBuffer();
            pdfViewer1.Invalidate();


But i'm not sure that exactly should be embedded in the case when Chinese, Korean and Japanese are used.
Looks like only used glyphs should be embedded.
Terry  
#8 Posted : Tuesday, August 14, 2018 2:24:21 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Thanks for replying, however this should not be necessary since 'Arial Unicode MS' is capable of representing both Russian and Japanese. Also, in my case the strings are entered interactively by a user and so I do not know the character sets in advance. A user may enter a single string containing mixed Russian, Japanese, Chinese, German, Polish, etc.
Terry  
#9 Posted : Tuesday, August 14, 2018 2:44:06 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Hi Paul,

Thanks for your second reply (containing the example code), and you are correct that "only used glyphs should be embedded." I'm investigating the problem of creating a font subset separately using native Windows & .NET API, but first I wanted to prove to myself that the new Pdfium API was capable of embedding an entire Unicode font to display a generic Unicode string, but this does not appear to be possible at the moment. So I will have to investigate an alternative approach.

Thanks for your help.

Terry.
Paul Rayman  
#10 Posted : Tuesday, August 14, 2018 3:10:23 AM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 10 times
Was thanked: 133 time(s) in 130 post(s)

FOXIT Phantom PDF splits such text to the separate objects

Untitled.pdf_decoded.pdf (30kb) downloaded 3 time(s).
Quote:
0 0 0 rg 0 0 0 RG 0 w /FXF1 12 Tf 1 0 0 1 0 0 Tm 96.911 757.479 TD[(This is a sample text with Russian)]TJ
/FXF2 12 Tf 1 0 0 1 0 0 Tm 277.511 757.479 TD[(              \n     )]TJ
/FXF3 12 Tf 1 0 0 1 0 0 Tm 397.175 757.479 TD[(АМ°НАє ЗС±№ѕо ЕШЅєЖ®АФґПґЩ.)]TJ
/FXF1 12 Tf 1 0 0 1 0 0 Tm 551.147 757.479 TD[( )]TJ




Probably somehow it can be done with a single object, but the original Pdfium API does not assume this and I do not know how to do this. I could look for a solution, in analogy with Windows fonts.
Does anyone know how a similar line could be drawn in Windows GDI?
How do I set the LOGFONT parameters in Windows to display a similar string?
Terry  
#11 Posted : Tuesday, August 14, 2018 4:50:20 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
Thanks for the information Paul, very interesting. I'm surprised that Foxit Phantom PDF splits the text in this manner. Previously I used iText (with Java) and Pdftron's Pdfnet (with C++) to insert such text into a PDF and in both cases the mixed character set text was inserted as a single object and a single subsetted font was embedded containing only the glyphs actually present in the text.

I understand that the Foxit/Debenu Quick PDF library also inserts such text as a single object, but I have yet to test this myself - I intend to investigate this now, so will let you know the outcome.

I should also mention that I want to insert the text into a Form XObject (which is referenced in the appearance stream of a widget annotation), not into the content stream of a page, so I'm not sure whether I can use the Pdfium 'PdfTextObject' to do this. At the moment I'm explicitly inserting all the low-level text and font operators ('BT', 'Tf', 'Td', 'Tj', 'ET', etc) myself, but this is a separate issue.

Terry.
Paul Rayman  
#12 Posted : Tuesday, August 14, 2018 5:35:24 AM(UTC)
Paul Rayman

Rank: Administration

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

Thanks: 10 times
Was thanked: 133 time(s) in 130 post(s)
Originally Posted by: Terry Go to Quoted Post

I should also mention that I want to insert the text into a Form XObject (which is referenced in the appearance stream of a widget annotation), not into the content stream of a page, so I'm not sure whether I can use the Pdfium 'PdfTextObject' to do this. At the moment I'm explicitly inserting all the low-level text and font operators ('BT', 'Tf', 'Td', 'Tj', 'ET', etc) myself, but this is a separate issue.


Pdfium.Net SDK contains tools that greatly facilitate this task.
For example, the following code generates the stream with the following text. All resources will be contained in the stream dictionary, so you can directly use this one as an appearance stream of widget annotation.

Code:
var form = PdfFormObject.Create(doc.Pages[0]);
var textObj = PdfTextObject.Create("Sample Text", 0, 0, PdfFont.CreateStock(doc, FontStockNames.Arial), 15.0f);
form.PageObjects.Add(textObj);
var stream = PdfTypeStream.Create();
bool b = Pdfium.FPDF_GenerateContentToStream(doc.Handle, form.PageObjects.Handle, stream.Handle, IntPtr.Zero);


Note:
q
/FXE1 gs
BT
1 0 0 1 0 0 Tm 0 0 TD 0 Tr
0 Tc 0 Tw
/FXF1 15 Tf
[(Sample Text)]TJ
ET
Q

imgFormAnnot.png (18kb) downloaded 7 time(s).
imgFormAnnot2.png (28kb) downloaded 6 time(s).
thanks 1 user thanked Paul Rayman for this useful post.
Terry on 8/14/2018(UTC)
Terry  
#13 Posted : Tuesday, August 14, 2018 8:28:25 AM(UTC)
Terry

Rank: Member

Groups: Registered
You have been a member since:: 7/26/2016(UTC)
Posts: 25
United Kingdom
Location: Somerset

Thanks: 5 times
That's a useful tip Paul, thanks. I was not aware of the 'FPDF_GenerateContentToStream()' method. Will investigate this further once I have solved my fonts problem!

Thanks for your continuing help.

Terry.
Users browsing this topic
Guest (6)
Similar Topics
Embedded fonts are not saved on incremental save (Common Questions)
by rhnatiuk 2/4/2021 5:21:33 AM(UTC)
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.