// hmm there does not seem to be a clear definition for StemV,
// this is close enough and I am told it doesn't usually get used.
fd.setStemV(fd.getFontBoundingBox().getWidth() * .13f);
CmapTable cmapTable = ttf.getCmap();
CmapSubtable uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_UNICODE,
CmapTable.ENCODING_UNICODE_2_0_FULL);
if (uniMap == null)
{
uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_UNICODE,
CmapTable.ENCODING_UNICODE_2_0_BMP);
}
if (uniMap == null)
{
uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
CmapTable.ENCODING_WIN_UNICODE);
}
if (uniMap == null)
{
// Microsoft's "Recommendations for OpenType Fonts" says that "Symbol" encoding
// actually means "Unicode, non-standard character set"
uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
CmapTable.ENCODING_WIN_SYMBOL);
}
if (uniMap == null)
{
// there should always be a usable cmap, if this happens we haven't tried hard enough
// to find one. Furthermore, if we loaded the font from disk then we should've checked
// first to see that it had a suitable cmap before calling createFontDescriptor
throw new IllegalArgumentException("ttf: no suitable cmap for font '" +
ttf.getNaming().getFontFamily() + "', found: " +
Arrays.toString(cmapTable.getCmaps()));
}
if (this.getFontEncoding() == null)
{
// todo: calling this.getFontEncoding() doesn't work if the font is loaded
// from the local system, because it relies on the FontDescriptor!
// We make do for now by returning an incomplete descriptor pending further
// refactoring of PDFont#determineEncoding().
return fd;
}
Map<Integer, String> codeToName = this.getFontEncoding().getCodeToNameMap();
int firstChar = Collections.min(codeToName.keySet());
int lastChar = Collections.max(codeToName.keySet());
HorizontalMetricsTable hMet = ttf.getHorizontalMetrics();
int[] widthValues = hMet.getAdvanceWidth();
// some monospaced fonts provide only one value for the width
// instead of an array containing the same value for every glyphid
boolean isMonospaced = fd.isFixedPitch() || widthValues.length == 1;
int nWidths = lastChar - firstChar + 1;
List<Integer> widths = new ArrayList<Integer>(nWidths);
// use the first width as default
// proportional fonts -> width of the .notdef character
// monospaced-fonts -> the first width
int defaultWidth = Math.round(widthValues[0] * scaling);
for (int i = 0; i < nWidths; i++)
{
widths.add(defaultWidth);
}
// A character code is mapped to a glyph name via the provided font encoding
// Afterwards, the glyph name is translated to a glyph ID.
// For details, see PDFReference16.pdf, Section 5.5.5, p.401
//
for (Map.Entry<Integer, String> e : codeToName.entrySet())
{
String name = e.getValue();
// pdf code to unicode by glyph list.
if (!name.equals(".notdef"))
{
String c = GlyphList.getAdobeGlyphList().toUnicode(name); // todo: we're supposed to use the 'provided font encoding'
int charCode = c.codePointAt(0);
int gid = uniMap.getGlyphId(charCode);
if (gid != 0)
{
if (isMonospaced)
{
widths.set(e.getKey() - firstChar, defaultWidth);