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);
            }
        }
Exemple #2
0
        /// <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
        }