static void Main() { var fonts = new[] { new Font("Arial", 7.5f, FontStyle.Regular), new Font("Arial", 8.25f, FontStyle.Regular) }; string textToMeasure = "START"; using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) { IntPtr hDC = g.GetHdc(); foreach (Font font in fonts) { float totalWidth = 0F; IntPtr hFont = font.ToHfont(); // Apply the font to dc SelectObject(hDC, hFont); int pairCount = GetKerningPairs(hDC, short.MaxValue, null); var lpkrnpair = new KERNINGPAIR[pairCount]; GetKerningPairs(hDC, pairCount, lpkrnpair); Console.WriteLine("\r\n" + font.ToString()); for (int ubound = textToMeasure.Length - 1, i = 0; i <= ubound; ++i) { char c = textToMeasure[i]; ABCFLOAT characterWidths = GetCharacterWidths(hDC, c); float charWidth = (characterWidths.abcfA + characterWidths.abcfB + characterWidths.abcfC); totalWidth += charWidth; int kerning = 0; if (i < ubound) { kerning = GetKerningBetweenCharacters(lpkrnpair, c, textToMeasure[i + 1]).iKernAmount; totalWidth += kerning; } Console.WriteLine(c + ": " + (charWidth + kerning) + " (" + charWidth + " + " + kerning + ")"); } Console.WriteLine("Total width: " + totalWidth); DeleteObject(hFont); } g.ReleaseHdc(hDC); } }
/// <summary> /// Gets the kerning information. /// </summary> /// <param name="font">The font.</param> /// <returns>The kerning information.</returns> public static Dictionary<char, Dictionary<char, int>> GetKerningInfo(this Font font) { var hdc = GetDC(NULL); var fontHandle = font.ToHfont(); var previousFont = SelectObject(hdc, fontHandle); try { var kerningPairs = new KERNINGPAIR[GetKerningPairs(hdc, -1, NULL)]; if (kerningPairs.Length > 0) { GetKerningPairs(hdc, kerningPairs.Length, kerningPairs); } return kerningPairs.GroupBy(i => i.First).ToDictionary(g => g.Key, g => g.ToDictionary(i => i.Second, i => i.KernAmount)); } finally { SelectObject(hdc, previousFont); DeleteObject(fontHandle); ReleaseDC(NULL, hdc); } }
public override void FillFontData(PDFFont pdfFont, TTFontData fontData) { SelectFont(pdfFont); fontData.PostcriptName = pdfFont.WFontName.Replace(" ", ""); if (pdfFont.Bold) { if (pdfFont.Italic) { fontData.PostcriptName = fontData.PostcriptName + ",BoldItalic"; } else { fontData.PostcriptName = fontData.PostcriptName + ",Bold"; } } else { if (pdfFont.Italic) { fontData.PostcriptName = fontData.PostcriptName + ",Italic"; } } fontData.FontFamily = pdfFont.WFontName; fontData.Type1 = false; fontData.IsUnicode = true; fontData.FontStretch = "/Normal"; fontData.Encoding = "WinAnsiEncoding"; fontData.HaveKerning = false; #if REPMAN_COMPACT #else fontData.EmHeight = family.GetEmHeight(fontstyle); fontData.LineSpacing = (int)Math.Round(1000.0 * family.GetLineSpacing(fontstyle) / fontData.EmHeight); fontData.Ascent = (int)Math.Round(1000.0 * family.GetCellAscent(fontstyle) / fontData.EmHeight); fontData.Descent = -(int)Math.Round(1000.0 * family.GetCellDescent(fontstyle) / fontData.EmHeight); fontData.Leading = fontData.LineSpacing - fontData.Ascent + fontData.Descent; //double multipli=(double)1.0*72/(double)dpix*(double)0.72); //data.FontWeight:=potm^.otmTextMetrics.tmWeight; //dataData.FontBBox.Left = Math.Round(data.FontBBox.Left*multipli); //fontData.FontBBox.Right = Round(data.FontBBox.Right*multipli); //data.FontBBox.Bottom:=Round(data.FontBBox.Bottom*multipli); //data.FontBBox.Top:=Round(data.FontBBox.Top*multipli); Font ft = (Font)font.Clone(); IntPtr hFt = ft.ToHfont(); SelectObject(hDC, hFt); if (fontData.Embedded) { ReadFontData(fontData); } // Assign widths list Monitor.Enter(tflag); try { if (WidthsCache == null) { WidthsCache = new SortedList <string, SortedList <char, GlyphInfo> >(); } if (WidthsCache.IndexOfKey(fontData.PostcriptName) < 0) { SortedList <char, GlyphInfo> nlist = new SortedList <char, GlyphInfo>(); WidthsCache.Add(fontData.PostcriptName, nlist); fontData.CacheWidths = nlist; } else { fontData.CacheWidths = WidthsCache[fontData.PostcriptName]; } } finally { Monitor.Exit(tflag); } GcpFlags nflags = GetFontLanguageInfo(hDC); fontData.HaveKerning = (nflags & GcpFlags.UseKerning) > 0; if (fontData.HaveKerning) { Monitor.Enter(tflag); try { if (KerningsCache == null) { KerningsCache = new SortedList <string, SortedList <ulong, int> >(); } if (KerningsCache.IndexOfKey(fontData.PostcriptName) >= 0) { fontData.Kernings = KerningsCache[fontData.PostcriptName]; } else { uint MAX_KER = 50000; SortedList <ulong, int> nkernin = new SortedList <ulong, int>(); KERNINGPAIR[] kerarray = new KERNINGPAIR[MAX_KER]; GCHandle kerHnd = GCHandle.Alloc(kerarray, GCHandleType.Pinned); try { uint numkernings = GetKerningPairs(hDC, MAX_KER, kerHnd.AddrOfPinnedObject()); for (uint i = 0; i < numkernings; i++) { //string nkey = kerarray[i].wFirst.ToString("00000") + // kerarray[i].wSecond.ToString("00000"); ulong nkey = (ulong)(kerarray[i].wFirst << 32) + (ulong)kerarray[i].wSecond; if (nkernin.IndexOfKey(nkey) < 0) { int amount = (int)Math.Round((double)-kerarray[i].iKernAmount / dpix * 72); nkernin.Add(nkey, amount); } } // Cache kernings KerningsCache.Add(fontData.PostcriptName, nkernin); } finally { kerHnd.Free(); } fontData.Kernings = nkernin; } } finally { Monitor.Exit(tflag); } } DeleteObject(hFt); #endif }