I'm embedding a TrueType font into pdf and thus need to create descriptor dictionary for it.
Among the required fields is StemV and I haven't found where in the ttf this info is stored.
I think I saw an hint somewhere that it is part of the CVT
program, but nothing specific.
So, my question is how to find out the StemV value for the given TrueType font. I want to read this value from the ttf file directly (as opposed to using ie windows API) as I want to write cross-platform solution.
Update:
Grep-ed LibreOffice 5.1.0.3 source and it seems that when exporting to pdf, the FontDescriptor
is generated in vcl/source/gdi/pdfwriter_impl.cxx
, method PDFWriterImpl::emitFontDescriptor()
. There, around line 3888 is following code:
// According to PDF reference 1.4 StemV is required
// seems a tad strange to me, but well ...
aLine.append( "\n"
"/StemV 80\n" );
The question is now why is it 80
, not 42
? Seriously though, if project like LibreOffice uses hardcoded constant, it seems to indicate that the value is either not stored into font file or reading it is extremely costly (ie requires implementing TrueType font engine to interpret the font program).
BTW, for those who are wondering what this StemV is - in the "PDF Reference sixth edition" it is described as "The thickness, measured horizontally, of the dominant vertical stems of glyphs in the font".
According to ISO 32000-1:2008, while StemH
is optional, StemV
is required (see Table 122). Alas, there doesn't seem to be a clear consensus on where to get this data from.
The variable is probably derived from Adobe's original Type 1 (CFF) font format:
The entry
StdVW
is an array with only one real number entry expressing the dominant width of vertical stems (measured horizontally in character space units). Typically, this will be the width of straight stems in lower case letters. (For an italic font program, give the width of the vertical stem measured at an angle perpendicular to the stem direction.) For example:
/StdVW [85] def
(Adobe Type 1 Font Format, February 1993, Version 1.1, p. 42)
This is an optional entry in the /Private
Dictionary of a CFF font.
However, Werner Lemberg states (http://blog.gmane.org/gmane.comp.fonts.freetype.devel/month=20130601)
The StemV value is not used by the PDF engine if the embedded font is either a Type 1 or CFF font; in that case the value from the private dictionary gets used. For a CID font, the value associated with the glyph's font DICT gets used.
In case there is no StemV value in the PDF, the following algorithm applies ...
which adds to the confusion, since it is marked "Required" in the PDF specs.
Apache FOP notes in its 'goals' under Fonts
.. if [important], parse the .pfb file to extract it when building the FOP xml metric file ..
(http://www.cs.helsinki.fi/group/xmltools/formatters/fop/fop-0.20.5/build/site/dev/fonts.html)
PDFLib uses FreeType, and the header file ft_font.h
contains a list:
+---------------------------------------------------------------------------+
Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+---------------------------------------------------------------------------+
(.. omitted..)
/*
* these defaults are used when the stem value
* must be derived from the name (unused)
*/
#define FNT_STEMV_MIN 50 /* minimum StemV value */
#define FNT_STEMV_LIGHT 71 /* light StemV value */
#define FNT_STEMV_NORMAL 109 /* normal StemV value */
#define FNT_STEMV_MEDIUM 125 /* mediumbold StemV value */
#define FNT_STEMV_SEMIBOLD 135 /* semibold StemV value */
#define FNT_STEMV_BOLD 165 /* bold StemV value */
#define FNT_STEMV_EXTRABOLD 201 /* extrabold StemV value */
#define FNT_STEMV_BLACK 241 /* black StemV value */
Note the "unused". This list also only appears in older versions of FreeType.
PrawnPDF just says (http://prawnpdf.org/docs/0.11.1/Prawn/Font/TTF.html)
stemV()
not sure how to compute this for true-type fonts...
The TrueType Embedder in Apache FontBox makes an educated guess:
// StemV - there's no true TTF equivalent of this, so we estimate it fd.setStemV(fd.getFontBoundingBox().getWidth() * .13f);
(https://pdfbox.apache.org/download.cgi) - where I feel I must add that it's better than nothing, but only by a very narrow margin. For most fonts, the relationship between stem width and bounding box is not this simple. There are also some famous fonts that fatten "inwards" and so their bounding boxes actually have the exact same values.
Further searching led me all the way back to a 1998 UseNet post:
.ttf tables, and PDF's StemV value
From: John Bley
Date: Tue, 16 Jun 1998 17:09:19 GMT
When embedding a TrueType font in PDF, I require a vertical stem width value - I can get all the other values (ascent, descent, italic angle, etc.) that I need from various .ttf tables, but I can't seem to locate or calculate the average or normal vertical (or horizontal) stem width anywhere. By watching an embedded PDF font, I know that the "hint" in the 'OS/2' table is not enough - it's a highly precise value, not a 1-10 kind of scale. Any clues? Thanks for your time!The value is not in TrueType fonts. You have to calculate it by analysis of, say, the cap I glyph. Don't worry too much about putting in a precise value: the value will only ever be used if the font is not present with the PDF file, when a vaguely similar font will be used instead. -- Laurence
(http://www.truetype-typography.com/ttqa_1998.htm)
The "'OS/2' table" hint, presumably, is usWeightClass
. While its values are defined in the range from 100 to 900, this is not a continuous range. Only the entire 100ths are used, and so it's a scale from 1-9 (not 1-10 as mentioned in the question above). The scale is derived from Microsoft's font definitions, which only has these 9 distinct values. (Note that the ft_font.h
file only lists 8 predefined stem values. Another problem, there.)
Using Adobe InDesign CS4, I created a small test PDF using the font Aller in Light, Regular, and Bold, and Arial in Regular, Bold, and Black weights (these are both TTF fonts) and found InDesign writes out the StemV's as
Aller-Light 68
Aller-Regular 100
Aller-Bold 144
Arial 88
Arial-Bold 136
Arial-Black 200
This shows InDesign uses some kind of heuristics to calculate the stem width for each individual font and does not rely on a fixed weight based table. It is not as simple as "the width of an uppercase 'I'", which are 69, 102, 147 (Aller) and 94.7, 144.5, 221.68 (Arial) design units, respectively. I tested deliberately with sans serif fonts, as the serifs on a serif font would need estimating the width somewhere halfway the glyph.
I exported the same document using InDesign CC 2014 and got the exact same values. I have no further ideas on how to find out where InDesign gets these values from.
(Later addition:) Minion Pro is a CFF flavour OpenType font and so it may contain a valid StdVW
value. After testing, I found it does: 79 StdVW
. Quite noteworthy: InDesign does not use this value but exports it as /StemV 80
instead. The value for Minion Pro Bold, 128, is correct but, at this point, I am positive this could be pure coincidence. With these two already different, I did not have further incentive to check either Minion Pro Semibold or Minion Black.
The least worst solution seems to be to read usWeightClass
out of the OS/2 header and map this directly to a reasonable value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With