/** * Builds vertical metrics with a custom CIDToGIDMap (for embedding font subset). */ private void BuildVerticalMetrics(Dictionary <int, int> cidToGid) { // The "vhea" and "vmtx" tables that specify vertical metrics shall never be used by a conforming // reader. The only way to specify vertical metrics in PDF shall be by means of the DW2 and W2 // entries in a CIDFont dictionary. if (!BuildVerticalHeader(cidFont)) { return; } float scaling = 1000f / ttf.Header.UnitsPerEm; VerticalHeaderTable vhea = ttf.VerticalHeader; VerticalMetricsTable vmtx = ttf.VerticalMetrics; GlyphTable glyf = ttf.Glyph; HorizontalMetricsTable hmtx = ttf.HorizontalMetrics; long v_y = (long)Math.Round(vhea.Ascender * scaling); long w1 = (long)Math.Round(-vhea.AdvanceHeightMax * scaling); PdfArray heights = new PdfArray(); PdfArray w2 = new PdfArray(); int prev = int.MinValue; // Use a sorted list to get an optimal width array ISet <int> keys = new HashSet <int>(cidToGid.Keys); foreach (int cid in keys) { // Unlike buildWidths, we look up with cid (not gid) here because this is // the original TTF, not the rebuilt one. GlyphData glyph = glyf.GetGlyph(cid); if (glyph == null) { continue; } long height = (long)Math.Round((glyph.YMaximum + vmtx.GetTopSideBearing(cid)) * scaling); long advance = (long)Math.Round(-vmtx.GetAdvanceHeight(cid) * scaling); if (height == v_y && advance == w1) { // skip default metrics continue; } // c [w1_1y v_1x v_1y w1_2y v_2x v_2y ... w1_ny v_nx v_ny] if (prev != cid - 1) { w2 = new PdfArray(); heights.Add(PdfInteger.Get(cid)); // c heights.Add(w2); } w2.Add(PdfInteger.Get(advance)); // w1_iy long width = (long)Math.Round(hmtx.GetAdvanceWidth(cid) * scaling); w2.Add(PdfInteger.Get(width / 2)); // v_ix w2.Add(PdfInteger.Get(height)); // v_iy prev = cid; } cidFont[PdfName.W2] = heights; }
private bool BuildVerticalHeader(PdfDictionary cidFont) { VerticalHeaderTable vhea = ttf.VerticalHeader; if (vhea == null) { Debug.WriteLine("warn: Font to be subset is set to vertical, but has no 'vhea' table"); return(false); } float scaling = 1000f / ttf.Header.UnitsPerEm; long v = (long)Math.Round(vhea.Ascender * scaling); long w1 = (long)Math.Round(-vhea.AdvanceHeightMax * scaling); if (v != 880 || w1 != -1000) { PdfArray cosDw2 = new PdfArray(); cosDw2.Add(PdfInteger.Get(v)); cosDw2.Add(PdfInteger.Get(w1)); cidFont[PdfName.DW2] = cosDw2; } return(true); }