32

Background:

I have PDF's I am programmatically generating. I need to be able to send the PDF directly to a printer from the server (not through an intermediate application). At the moment I can do all of the above (generate PDF, send to printer), but because the fonts aren't embedded in the PDF the printer is doing font substitution.

Why the fonts aren't embedded when generated:

I am creating PDF's using SQL Reporting Services 2008. There is a known issue with SQL Reporting Services in that it will not embed fonts (unless a series of requirements are met - http://technet.microsoft.com/en-us/library/ms159713%28SQL.100%29.aspx). Don't ask me why, the PDF meets all of MS's listed requirements and the fonts still show up as not embedded - there is no real control over whether the fonts are embedded, so I have accepted that this isn't working and moved on. The suggested workaround from Microsoft (Link under 'When will Reporting Services do font embedding') is to post process the PDF to manually embed the fonts.

Goal Take an already generated PDF document, programmatically 'open' it and embed the fonts, resave the PDF.

Approach I was pointed towards iTextSharp, but most of the examples are for the Java version and I'm having trouble translating to the iTextSharp version (I can't find any documentation for iTextSharp).

I am working on this post for what I need to do: Itext embed font in a PDF.

However for the life of me, I cannot seem to use the ByteArrayOutputStream object. It can't seem to find it. I've researched and researched but nobody seems to say what class it's in or where I find it so I can include it in the using statements. I've even cracked open Reflector and can't seem to find it anywhere.

This is what I have so far and it compiles etc. etc. (result is my byte[] of the generated PDF).

PdfReader pdf = new PdfReader(result);            
BaseFont unicode = BaseFont.CreateFont("Georgia", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
// the next line doesn't work as I need a ByteArrayOutputStream variable to pass in
PdfStamper stamper = new PdfStamper(pdf, MISSINGBYTEARRAYOUTPUTSTREAMVARIABLE);
stamper.AcroFields.SetFieldProperty("test", "textfont", unicode, null); 
stamper.Close();
pdf.Close();

So can anybody either help me with using iTextSharp to embed fonts into a PDF or point me in the right direction?

I'm more than happy to use any other solutions other than iTextSharp to complete this goal, but it needs to be free and able to be used by a business for an internal application (i.e. Affero GPL).

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
hanzworld
  • 1,289
  • 1
  • 14
  • 22
  • Could you give the names of the fonts that you need to be embed? (Some fonts do have licenses which don't allow embedding, and most PDF processing or creating software does honor the respective flags in the font files and choose to not embed t hem...) – Kurt Pfeifle Nov 20 '10 at 17:28
  • Sure! Georgia and Calibri - I've checked that we have TrueType versions and (well, according to Windows) they both have the 'Font embedability' tag set to 'Editable' - I gather this is the right setting? Thanks for any help! – hanzworld Nov 21 '10 at 02:53
  • For anyone who reads this later on, both of these methods worked. SQL Reporting Services finally embedded fonts correctly after many updates / hotfixes and could be sent straight to the printer. Additionlly, called Ghostscript using ProcessInfo from .NET could post-process the PDF. – hanzworld Aug 31 '11 at 00:42

4 Answers4

39

This may not be the answer you are looking for (since you want to get your problems solved programmatically, not by an external tool).

But you can use Ghostscript commandline to embed missing fonts in retrospect to PDFs which have not embedded them:

gs \
  -sFONTPATH=/path/to/fonts:/another/dir/with/more/fonts \
  -o output-pdf-with-embedded-fonts.pdf \
  -sDEVICE=pdfwrite \
  -dPDFSETTINGS=/prepress \
   input-pdf-where-some-fonts-are-not-embedded.pdf

One important thing is that the missing fonts are all available in one of the directories pointed to by the -sFontPath=... switch.

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
  • Hey thanks for this - I had a quick go to see the output of this, and the outputtting PDF does indeed have embedded fonts - but it's replaced all the fonts with Helvetica! I can't make heads or tails of how to correct this. Any ideas? – hanzworld Nov 23 '10 at 23:59
  • 1
    @hanzworld: Can you provide the output of `pdffonts.exe original.pdf` and `pdffonts.exe processed.pdf`? (`pdffonts.exe` is part of the XPDF CLI utilities available here: http://www.foolabs.com/xpdf/download.html – Kurt Pfeifle Nov 24 '10 at 22:51
  • Original PDF: name type emb sub uni object ID ----------------------- ----------- --- --- --- --------- Calibri TrueType no no no 3 0 Georgia,BoldItalic TrueType no no no 4 0 Calibri,Bold TrueType no no no 5 0 Georgia,Italic TrueType no no no 9 0 – hanzworld Nov 28 '10 at 23:00
  • New PDF: name type emb sub uni object ID ------------------------------------ ----------------- --- --- --- --------- DWVDEF+Helvetica-Bold Type 1C yes yes no 10 0 VKBFCO+Helvetica Type 1C yes yes no 8 0 – hanzworld Nov 28 '10 at 23:00
  • 1
    Hey, hanzworld: as I told you -- **One important thing is that the missing fonts are all available in one of the directories pointed to by the `-sFONTPATH=...` switch**. Did you do this?!? Ghostscript didn't find the fonts required (Calibri, Georgia). Therefor, it used Helvetica as a substitute font. Just copy Calibri + Calibri,Bold + Georgia,BoldItalic to any path, then use `-sFONTPATH=/path/to/where/calibri-etc/are/copied/to/` with your Ghostscript command... (note the changed spelling of `-sFONTPATH...` – Kurt Pfeifle Dec 25 '10 at 14:01
  • I realise it's late, but thank you for patient help with this and debugging the problem. – hanzworld Aug 31 '11 at 00:38
  • 1
    On win32, if you have installed ghostScript, the command may look like: gswin32 -sFONTPATH=C:\Windows\Fonts -o output-pdf-with-embedded-fonts.pdf -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress input-pdf-where-some-fonts-are-not-embedded.pdf – fstang Jun 16 '14 at 07:32
  • An improvement to my previous comment(the above one): use gswin32c instead of gswin32, since the former is the command line version and the latter is the gui version. – fstang Jun 16 '14 at 08:02
  • Thanks for reminding to put the font directory, otherwise it didn't work. – Amir Aug 07 '16 at 15:30
  • 1
    This breaks the PDF form fields (in case you're looking for an answer with PDF forms not having embedded fonts). I wonder if there's a `gs` command argument to preserve that? – Fuhrmanator Aug 30 '18 at 05:22
  • 1
    @Fuhrmanator: FOSS software and PDF forms -- a long chapter in the book "List of important functionality missing or sucking in FOSS".... – Kurt Pfeifle Aug 30 '18 at 08:30
  • Finally, thank you! For any Windows user: I downloaded GhostScript, opened a CMD windows in its `bin` dir, and ran: `gswin64.exe -sFONTPATH=C://temp/font -o C://temp/output.pdf -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress C://temp/input.pdf` – Johannes Mar 14 '22 at 14:38
16

Besides Ghostscript, it is also possible to use Poppler and Cairo. There is a command pdftocairo from Poppler that converts PDF to PDF via pdftocairo -pdf input.pdf output.pdf. It also considers font substitutions set in a Fontconfig configuration file. This is very helpful if you do not have all fonts on your system that are referenced in a PDF file, but know which other font you have installed is a good-looking replacement. After processing, the substitution font is embedded.

Michael Fiedler
  • 191
  • 1
  • 2
  • 1
    + 1 : -- Hey, I didn't know that! :-) I'll trust for now that it works as you describe. Will test later. But if it doesn't work, I'll have to take back my u p v o t e again... :-) – Kurt Pfeifle Dec 22 '14 at 17:06
  • This is so much easier than using `gs` – I might even be able to remember this command. – fission Jun 23 '15 at 07:06
  • 1
    This works great. Just a note for Windows cygwin users - if you try to run this under cygwin it may use a different font changing the appearance of the image. Using [Poppler for Windows](http://blog.alivate.com.au/poppler-windows/) from a standard Command Prompt works great. Thank you for posting this answer. – zelanix Sep 15 '16 at 09:10
  • Worked perfect on Ubuntu ! – user2939212 Jul 16 '18 at 20:41
  • Will poppler preserve PDF form structure when it does this conversion to cairo? The `gs` answer breaks the forms. – Fuhrmanator Aug 30 '18 at 06:25
  • @Fuhrmanator: FOSS software and PDF forms -- a long chapter in the book "List of important functionality missing or sucking in FOSS".... – Kurt Pfeifle Aug 30 '18 at 08:29
1

I had this problem on a Mac with a PDF I was submitting to IEEE. Using Adobe Reader and Preview, I was able to get around this. I think any pdf printer might work in place of Preview if you are on a PC.

Here are the steps I took. You can individually fix each figure, or fix the whole document.

  1. Open at pdf file using Adobe Reader.

  2. Right click on image, and click “Document Properties.”

  3. Click “Fonts.” Check to see if the font isn’t embedded. Should say “Courier” or other font name.

  4. If your pdf isn’t a standard page size, click on “Description” and look at the page size. Write this down. Ex. 19.4 x 5.22 in.

  5. Open the pdf up in Preview. Go to File->Print. If using a pdf that isn’t a standard page size, click on Paper Size and choose custom. You will need to create a custom page size that is equal to the one you wrote down in step 4. Don’t forget to zero the margins to 0 for all sides. After doing that, you’ll need to set the scale of the print in the print dialog to 100%.

  6. In the lower left of the print dialog (in Preview on a Mac), click “PDF” to print the PDF to a new PDF. Select the destination and print.

  7. Open the new pdf up in Adobe Reader and verify that the fonts are now embedded.

I hope this helps.

Michael
  • 11
  • 1
1

I had this problem today with an existing PDF I uploaded to lulu.com to make a printed copy. It was rejected for not having all fonts embedded.

I found that if I opened it in Acrobat X and Saved out as postscript .ps file, then when I double clicked this .ps file in File Explorer, it opened in Acrobat X Distiller, and this automatically created a new PDF file with all fonts embedded!

Naturally this would mean you must have all the fonts needed on your computer. Otherwise a program like InFix can make font substitutions.