Alrighty, I promise this is the closest I'll ever get to a "code for me" question :) If this doesn't drum up any responses I'll bite the bullet and build an OTF parser to check for the existence of a CFF table.
This info is available in the Windows font preview ('TrueType outlines' vs 'PostScript outlines'), so presumably there's a WinAPI function to this effect, but damned if I can find it.
Thoughts anyone?
ps - It's not a dealbreaker if only installed fonts can be checked, but checking files would be preferable.
You can do this using the GetFontData function.
Create the font in question and select it into a DC, then call GetFontData to query the size of the CFF table. This will only succeed if the font has PostScript outlines.
DWORD dwSize = GetFontData(hdc, ' FFC', 0, nullptr, 0);
if (dwSize && dwSize != GDI_ERROR)
{
// has PostScript outlines
}
The OpenType spec says:
OpenType fonts containing CFF data should use the tag 'OTTO' as the sfnt version number.
So, if the first four bytes of the file spell "OTTO" it uses PostScript outlines. Could it be simpler!? Tested & working so far, but I'll probably use GetFontData in the end.
Your best bet indeed seems to be to directly read the font tables from the font file itself. This sample here will give to a head start, assuming you're already familiar with the font tables. If not, read the links in the Reference section at the bottom of the article.
The first 4 bytes of a OpenType file who has a CFF block are "OTTO".
Related
The Problem
I am loading the classic serife.fon file from Microsoft Windows using FreeType.
Here is how I set the size:
FT_Set_Pixel_Sizes(face, 0, fontHeight);
I use 0 for the fontWidth so that it will be auto-calculated based on the height.
How do I find the correct value for fontHeight such that the resulting font will be exactly 9 pixels tall?
Notes
Using trial and error, I know that the correct value is 32 - but I don't understand why.
I am not sure how relevant this is for bitmap fonts, but according to the docs:
pixel_size = point_size * resolution / 72
Substituting in the values:
point_size = 32
resolution = 96 (from FT_Get_WinFNT_Header)
gives:
pixel_size = 42.6666666
This is a long way from our target height of 9!
The docs do go on to say:
pixel_size computed in the above formula does not directly relate to the size of characters on the screen. It simply is the size of the EM square if it was to be displayed. Each font designer is free to place its glyphs as it pleases him within the square.
But again, I am not sure if this is relevant for bitmap fonts.
fon files are exe files with a fnt payload, where the fnt payload can be a vector or raster font. If this is a raster font (which is most likely) then the dfPixHeight value in the fnt header will tell you what size it's meant to be, which is exposed by FreeType2 as the pixel_height field of the FT_WinFNT_Header.
(And of course, note that using any size other than "the actual raster-size of the FNT" is going to lead to hilarious headaches because bitmap scaling is the kind of madness that's so bad, OpenType instead went with "just embed as many bitmaps as you need, at however many sizes you need, because that's the only way your bitmaps are going to look good")
The FNT-specific FT2 documentation can be found over on https://www.freetype.org/freetype2/docs/reference/ft2-winfnt_fonts.html but you may need to read it in conjunction with https://jeffpar.github.io/kbarchive/kb/065/Q65123 (or https://web.archive.org/web/20120215123301/http://support.microsoft.com/kb/65123) to find any further mappings that you might need between names/fields as defined in the FNT spec and FT2's naming conventions.
Is there an option for to me to ask Ghostscript to indent the Postscript it creates?
Everything starts at the beginning of a line and I find it difficult to follow.
Alternatively, I am using Emacs and ps-mode.
If anyone know how to indent code in this mode I would appreciate a tip (apologize because this may not be relevant to this StackExchange)
No, there is no option for indenting the output.
PostScript is pretty much regarded as a write-only language anyway, and the output of ps2write (which is what I assume you are using though you don't say) is particularly difficult since it fundamentally outputs PDF syntax with a PostScript program on the front to parse it into PostScript operations.
Why do you want to read it ?
[EDIT]
You can always edit your question, you don't need to post a new answer.
I'm afraid what you want to do isn't as simple as you might think.
It might be possible for this use case if the PDF files you receive are always created the same way, but there are significant problems.
The font you use as a substitute for the missing font must be encoded the same way. Say for example the font in the PDF file is encoded so that 0x41 is 'A', you need to make sure that the replacement font is also encoded so that 0x41 is an 'A'. So just the findfont, scalefont, setfont sequence is not always going to be sufficient, sometimes you will need to re-encode the font.
CIDFonts will be a major stumbling block. Firstly because ps2write simply doesn't emit CIDFonts at all. These were not part of level 2 PostScript. As a result all text in a CIDFont will be embedded as bitmaps. If your original file doesn't contain the CIDFont then you'll get the fallback CIDFont bitmapped.
Secondly CIDFonts can use multiple-byte character codes, of variable length. You can't simply replace a CIDFont with a Font, it just won't work.
The best solution, obviously, is to have the PDF files created with the fonts required embedded. This is best practice. If you can't get that, then I'd suggest that rather than trying to hand edit PostScript, you use the fontmap.GS and cidfmap files which Ghostscript uses to find font.
Ghostscript already has a load of code to do font substitution automatically, using both Fonts and CIDFonts as substitutes, and it does all the hard work of re-encoding the fonts or building CMaps as required. If you are on Windows much of this may already be done for you, when you install Ghostscript it will ask if you want to create font mappings. If you said yes then it will
Add the font substitutions you want to use in those files (they have comments explaining the layout) and then use the pdfwrite device to make a new PDF file. Set EmbedAllFonts to true (you may need to add a AlwayEmbed font array as well, listing the fonts specifically) and SubsetFonts to false.
That should create a new PDF file where the missing fonts have been replaced by your defined substitutes, those substitutes will have been embedded in the new PDF file and they have will not been subset (Acrobat will generally refuse to edit text in a subset font).
The switches I mentioned above are standard Adobe Distiller parameters, but they are documented for pdfwrite here. There's some documentation on adding fonts here and here and specifically for CIDFonts here.
Basically I'd suggest you define your substitutions and let Ghostscript do the work for you.
This is not an answer to the problem but rather an answer to KenS's question about "Why do you want to read it?"
I tried to put it in the comment box but it was too long.
I am a retired engineer with a strong programming background.
I would like to read and understand the postscript code for the reason shown below.
I play duplicate bridge as a hobby. I recieve a PDF file of what is know as a convention card (a single page document of bridge agreements).
Frequently I would like to edit these files.
When I open with Adobe Illustrator I have to spend a significant amount of time replacing fonts that are not on my system with fonts that I do have.
I can take the PDF and export it as a postscript file using Ghostscript.
I was going to write a little program to replace the embedded fonts with the fonts that I use to replace them.
I was going to leave the postscript file unaltered and insert things like
/HelveticaMonospacedPro-RG findfont
12 scalefont setfont
just above where the text is written.
I was planning on using the fonts that I have on my system (e.g., HelveticaMonospacedPro-RG).
I am trying to create my own tool for creating the pdf file. Every thing is going well, Only thing I miss is the font descriptors. Kindly let me know the correct values of capheight, ascent, descent, glag, italic angle from afm/pfa/pfb or any tool available to genrate the same
Fontographer will show those values. A bit pricey for just collecting statistics. My copy is old, back when Macromedia owned it. FontLab does now. See http://www.fontlab.com/font-editor/fontographer/
Given an HFONT, how do I tell if it's a symbol font? A pdf library I'm using needs to treat symbol fonts differently, so I need a way to programatically tell if any given font is a symbol font or not.
Use GetObject to get the font's properties to a LOGFONT structure. Check the lfCharSet member; if it's SYMBOL_CHARSET, you have a symbol font.
Mark Ransom's answer is going to work 99.999% of the time, but there's a theoretical possibility that it could give the wrong answer.
To avoid this possibility, you should use GetTextMetrics to get the TEXTMETRICS of the actual font and check if the tmCharSet is SYMBOL_CHARSET.
What's the difference between checking lfCharSet and tmCharSet?
When you create an HFONT, Windows makes an internal copy of the LOGFONT. It describes the font you want, which could be different than the font you get.
When you select the HFONT into a device (or information) context, the font mapper finds the actual font that best matches the LOGFONT associated with that HFONT. The best match, however, might not be an exact match. So when you need to find out something about the actual font, you should take care to query the HDC rather than the HFONT.
If you query the HFONT with GetObject, you just get the original LOGFONT back. GetObject doesn't tell you anything about the actual font because it doesn't know what actual font the font mapper chose (or will choose).
APIs that ask about the font selected into a particular DC, like GetTextMetrics, GetTextFace, etc., will give you information about the actual font.
For this problem, Mark's answer (using GetObject) is probably always going to work, because the odds of the font mapper choosing a symbol font when you want a textual font (or vice versa) are minuscule. In general, though, when you want to know something about the actual font, find a way to ask the HDC.
Anyone know the right places to hook into ghostscript, so that when interpreting a ps file, I can get logs of all calls of the form:
draw_character(float x, float y, string font_name, int char_id); ?
Basically I want to take a postscript file, and get a list of where all characters are drawn to the screen.
Thanks!
I'm not sure if this answer is going to help you... but do you know how to harvest debugging information from Ghostscript on the commandline? Simply add "-dDEBUG" to the commandline and it will spit out lots of additional info. To get debugging info from only specific topics, you have these options:
-dCCFONTDEBUG Compiled-in Fonts
-dCFFDEBUG CFF Fonts
-dCMAPDEBUG CMAP
-dDOCIEDEBUG CIE color
-dEPSDEBUG EPS handling
-dFAPIDEBUG Font API
-dINITDEBUG Initialization
-dPDFDEBUG PDF Interpreter
-dPDFOPTDEBUG PDF Optimizer (Linearizer)
-dPDFWRDEBUG PDF Writer
-dSETPDDEBUG setpagedevice
-dSTRESDEBUG Static GS Resources
-dTTFDEBUG TTF Fonts
-dVGIFDEBUG ViewGIF
-dVJPGDEBUG ViewJPEG
Possibly, a PostScript programmer guru could write a little PostScript program that could do what you want by re-defining one of the operators (showglyph?) in a way that it prints out the info you want instead of (or before) drawing each individual character and run that against your target PS file.
Maybe you should ask your question in comp.text.pdf or in comp.lang.postscript ?