Is there a way to programmatically determine if a font file has a specific Unicode Glyph?

前端 未结 6 914
花落未央
花落未央 2020-11-27 04:19

I\'m working on a project that generates PDFs that can contain fairly complex math and science formulas. The text is rendered in Times New Roman, which has pretty good Unic

6条回答
  •  萌比男神i
    2020-11-27 05:13

    Scott's answer is good. Here is another approach that is probably faster if checking just a couple of strings per font (in our case 1 string per font). But probably slower if you are using one font to check a ton of text.

        [DllImport("gdi32.dll", EntryPoint = "CreateDC", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CreateDC(string lpszDriver, string lpszDeviceName, string lpszOutput, IntPtr devMode);
    
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern bool DeleteDC(IntPtr hdc);
    
        [DllImport("Gdi32.dll")]
        private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
    
        [DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
        private static extern int GetGlyphIndices(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpstr, int c,
                                                  Int16[] pgi, int fl);
    
        /// 
        /// Returns true if the passed in string can be displayed using the passed in fontname. It checks the font to 
        /// see if it has glyphs for all the chars in the string.
        /// 
        /// The name of the font to check.
        /// The text to check for glyphs of.
        /// 
        public static bool CanDisplayString(string fontName, string text)
        {
            try
            {
                IntPtr hdc = CreateDC("DISPLAY", null, null, IntPtr.Zero);
                if (hdc != IntPtr.Zero)
                {
                    using (Font font = new Font(new FontFamily(fontName), 12, FontStyle.Regular, GraphicsUnit.Point))
                    {
                        SelectObject(hdc, font.ToHfont());
                        int count = text.Length;
                        Int16[] rtcode = new Int16[count];
                        GetGlyphIndices(hdc, text, count, rtcode, 0xffff);
                        DeleteDC(hdc);
    
                        foreach (Int16 code in rtcode)
                            if (code == 0)
                                return false;
                    }
                }
            }
            catch (Exception)
            {
                // nada - return true
                Trap.trap();
            }
            return true;
        }
    

提交回复
热议问题