Altering an embedded TrueType font so it will be usable by Windows GDI
Asked Answered
M

2

6

I am trying to render PDF content to a GDI device context (a 24bit bitmap to be exact). Parsing the PDF stream into PDF objects and rendering the PDF commands from the content dictionary works well, including font rendering.

Embedded fonts are decompressed from their FontFile streams and "loaded" using AddFontMemResourceEx. Now some embedded fonts remove some TrueType tables that are needed by GDI, like the 'name' table. Because of this, I tried to modify the font by parsing the TrueType subset font into it's tables and modify those tables that have data missing / missing tables are regenerated with as correct information as possible.

I use the Microsoft Font Validator tool to see how "correct" the generated font is. I still get a few errors, like for the maxp table the max values are usually too large (it is a subset) or the xAvgCharWidth field does not equal the calculated value of the 'OS/2' table is not correct but this does not stop other embedded fonts to be useable. The fonts embedded using PDFCreator are the ones that are problematic.

Questions:

  1. How can I determine what I need to change to the font file in order for GDI to be able to use it?
  2. Are there any other font validation tools that might give me insight into what is still wrong with the fontfile?

If needed: I can make an original fontfile and an altered fontfile available for download somewhere.

What modifications are made so far:

  • Make sure there is a 'head', 'hhea', 'maxp' and 'OS/2' section.
  • If we have a symbol font, clear out Panose and Unicode fields in the 'OS/2' section
  • Fill in correct values for WInAscent/Desc and TypoAsc/Desc if they we're zero.
  • Fill in acceptable values for super/subscript/underline positions and sizes.
  • Scan all glyphs that are left en fill in X/Y min/max values in head.
  • Rebuild the name section with information from the PDF file it came from.
Mastat answered 14/6, 2010 at 10:10 Comment(4)
PDFCreator relies on Ghostscript to produce the PDF. PDFCreator's input is PostScript, which (on Windows) usually is originating as output of a PostScript Printer Driver (most of the time, Adobe's PS Driver). So, the question is: are you in full control of your workflow? Or do you have to process PDFs which were generated by a PDFCreator somewhere, sometime beyond your control? If you are in full control, you could set up your PDFCreator workflow to embed original TrueType fonts used by the original (non-PostScript) document format, instead of having the workflow convert the fonts to PS Type1.Kippar
@pipitas: The source PDFs are considered "beyond our control". Currently we have a guideline that says: when using PDFCreator, do not use embedded fonts. The main reason I really want to solve this issue is the full understanding of the truetype font loading requirements on Windows. If I can use GDI to draw my text, I can avoid depending on other dlls, libraries with their licenses and patent issues etc etc. But in the end I really like to solve this nagging issue albeit it is now lower on the prio list due to the guideline.Mastat
Well, if your problem mainly occurs with PDFCreator's output, but you are not allowed to "fix" the cause of that problem at its root (by a stupid guideline that says "Don't do for your PDFs what all recent standardization efforts [PDF/X, PDF/A] recommended [namely, embedding fonts]!", then I'm stumped...Kippar
I really would like a fix, but all tools say the font I have is valid and freetype can use it unmodified, but not GDI. And it will not tell me what it thinks is wrong with it. As of therecent standardization: Those are made to solve specific problems for exactness/X and long term storage/A and that is not the problem we have here. Being able to render the PDF correctly even with a substitute font is okay for this application. But in a perfect world all embedded font programs are valid or I should be able to use embedded font programs after simple modifications. This case does not work.Mastat
M
4

Almost a year late, but I found the answer:

The font kind (symbol or not) should be the same for the 'cmap' table and the 'name' table. So if the cmap has a 3,0,4 cmap (MS, symbol, segment delta coding) and the name table contains 3,1,$0409 (MS, Unicode, enUS) entries, the font will not load.

It looks like the presence of a 'symbol cmap' determines if the font is considered a symbol font by Windows; flags in 'OS/2' don't seem to matter.

So if a font seems correct using 'Microsoft Font Validator', check if the symbol/unicode fields line up in the 'cmap' and 'name' tables.

Mastat answered 15/6, 2011 at 19:50 Comment(3)
i was just looking around and it appears WPF may have this as well in .NET 4.0 using PresentationCore as a reference: msdn.microsoft.com/en-us/library/…Wiltshire
I do not have extensive experience with WPF but it seems/looks like you can use OpenType fonts that have no cmap and you address the glyphs on glyphid. If you try to do so in GDI it won't work. Thanks for pointing it out.Mastat
I haven't dug into it all that much, but I did run across this whitepaper on font selection in WPF that is very detailed in showing how WPF determines fonts from the tables. It's an interesting read.Wiltshire
W
2

With AddMemoryFont in GDI+ you can check it's Status for any errors in the memory font, like NotTrueTypeFont for example.

One option for GDI may be to try to load the embedded font into a document/form yourself with TTLoadEmbeddedFont and then check any errors returned from the error messages. The only functions that supply more information than this one are CreateFontPackage/MergeFontPackage, and their error codes, but I do fail to see how they can be used in your situation.

Barring all this, have you had a chance to review PDFCreator's source code (assuming you're using the open source one as opposed to the commercial one)?

Wiltshire answered 18/6, 2010 at 2:35 Comment(12)
This function / status codes do not provide enough information to see why it is considered not a truetype valid font. I try to supply a truetype font program that adheres to the requirements (all required tables present etc etc) but somehow do I fail to see what is missing/wrong. Also, I use GDI and not GDI+ but if I could get the information what I need to change to the font and make things working... Somewhere in the GDI implementation for loading truetype fonts is the font program rejected and I want to know why so I can alter it and use the embedded font.Mastat
Ah, sorry about the GDI+. Yeah, GDI checks only a certain number of things. I've updated the answer above.Wiltshire
I tried MergeFontPackage to craete a correct font or get some directions what is wrong with it. And voila.. no errors we got a new font file. Unfortunately it didn't work; better yet, the font package it created was the same byte for byte. So this did not give me the insight what was wrong with the font program plus did not yield a readable font program. I will try TTLoadEmbedded to see what that brings me tomorrow.Mastat
TTLoadEmbedded expects a stream of an OTF file (a truetype with an OTF header in front of it). After creating just such a file in memory and getting all the bugs out it fails with a message E_ADDFONTFAILED (eg the truetype font is unpacked correctly but the Windows font manager cannot load it. So it is still unknown why the Windows font manager wont load the font in question. As for the PDFCreator source: I see tat the PDF is created by the Ghostscript embedded module and I can check the results (eg what it has done) so this won't give me an answer either.:-( Thanks anyhow for the leads!Mastat
Ah, therein lies the issue if it is Ghostscript. Without knowing too much about GS, it's likely GS is working within the bounds of conversion to some kind of PostScript to support the Acrobat format. This is less of a question now about extracting and normalizing the font from a GDI perspective and more about GS and Acrobat. I'd start with the GS sourcecode directly, like svn.ghostscript.com/ghostscript/trunk/gs/lib.Wiltshire
@Otaku: My problem is not with GS, but with Windows not giving me the information what made it beleive the font program is corrupt. What GS produces is readable by Freetype2 test programs so it is just Windos GDI being picky..Mastat
Again, I'd encourage you to look beyond GDI here for the solution. Freetype2 supports many formats that GDI doesn't, or doesn't easily. If it is supported by GDI at all, you can always test in a GDI-font-rendering program, such as Word 2007 (embed the font in the OPC, set up the relationships and create text using that) - my guess here is that it will fail. We're talking about PDF here, kind of it's own little mini-platform - it may be a different format for PDF (CID-keyed Type 1 fonts) or as drastic as turning the TTFs into bitmapped glyphs (which GDI can get, but it's a real pain).Wiltshire
I think I will end up using Freetype2. The main reason for the bounty is: because I don't get it why GDI/Windows font manager refuses to use the font in question. Probably it is a single bit somewhere that needs to be changed and voila a working font. It did work already for a lot of other embedded fonts in the PDF renderer. The main reaon I wish to use GDi is that I can replace the PDF merge routines I need with a flatten PDF merge rolutine where I draw a PDf into another and if I do that using GDI and an EMF I end up with a much smalles and cleaner PDf (I need to store 300k PDFs/yr).Mastat
I gave you the bounty because you realy helped me in my investigation. Unfortunately I did not get the answer to the question. Thanks anyhow for all your suggestions!Mastat
Thanks Ritsaert. I'd be interested in seeing the results with Freetype2.Wiltshire
Finally I did find the answer (albeit almost a year late). I never got to using Freetype2 so probably I never will now that it works.Mastat
@Ritsaert Hornstra: Great to hear you finally got the answer.Wiltshire

© 2022 - 2024 — McMap. All rights reserved.