una tipografia para letras illustrator identificar fuentes fuente estilo escritura descargar dafont como bonitas asp.net vb.net unicode fonts

asp.net - tipografia - ¿Hay alguna forma de determinar mediante programación si un archivo de fuente tiene un glifo Unicode específico?



fuentes de letras bonitas (5)

Aquí hay un pase utilizando c # y la API de Windows.

[DllImport("gdi32.dll")] public static extern uint GetFontUnicodeRanges(IntPtr hdc, IntPtr lpgs); [DllImport("gdi32.dll")] public extern static IntPtr SelectObject(IntPtr hDC, IntPtr hObject); public struct FontRange { public UInt16 Low; public UInt16 High; } public List<FontRange> GetUnicodeRangesForFont(Font font) { Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr hdc = g.GetHdc(); IntPtr hFont = font.ToHfont(); IntPtr old = SelectObject(hdc, hFont); uint size = GetFontUnicodeRanges(hdc, IntPtr.Zero); IntPtr glyphSet = Marshal.AllocHGlobal((int)size); GetFontUnicodeRanges(hdc, glyphSet); List<FontRange> fontRanges = new List<FontRange>(); int count = Marshal.ReadInt32(glyphSet, 12); for (int i = 0; i < count; i++) { FontRange range = new FontRange(); range.Low = (UInt16)Marshal.ReadInt16(glyphSet, 16 + i * 4); range.High = (UInt16)(range.Low + Marshal.ReadInt16(glyphSet, 18 + i * 4) - 1); fontRanges.Add(range); } SelectObject(hdc, old); Marshal.FreeHGlobal(glyphSet); g.ReleaseHdc(hdc); g.Dispose(); return fontRanges; } public bool CheckIfCharInFont(char character, Font font) { UInt16 intval = Convert.ToUInt16(character); List<FontRange> ranges = GetUnicodeRangesForFont(font); bool isCharacterPresent = false; foreach (FontRange range in ranges) { if (intval >= range.Low && intval <= range.High) { isCharacterPresent = true; break; } } return isCharacterPresent; }

Luego, dado un carácter a Comprobar que quieres verificar y una Fuente de Font para probarlo en contra ...

if (!CheckIfCharInFont(toCheck, theFont) { // not present }

Mismo código usando VB.Net

<DllImport("gdi32.dll")> _ Public Shared Function GetFontUnicodeRanges(ByVal hds As IntPtr, ByVal lpgs As IntPtr) As UInteger End Function <DllImport("gdi32.dll")> _ Public Shared Function SelectObject(ByVal hDc As IntPtr, ByVal hObject As IntPtr) As IntPtr End Function Public Structure FontRange Public Low As UInt16 Public High As UInt16 End Structure Public Function GetUnicodeRangesForFont(ByVal font As Font) As List(Of FontRange) Dim g As Graphics Dim hdc, hFont, old, glyphSet As IntPtr Dim size As UInteger Dim fontRanges As List(Of FontRange) Dim count As Integer g = Graphics.FromHwnd(IntPtr.Zero) hdc = g.GetHdc() hFont = font.ToHfont() old = SelectObject(hdc, hFont) size = GetFontUnicodeRanges(hdc, IntPtr.Zero) glyphSet = Marshal.AllocHGlobal(CInt(size)) GetFontUnicodeRanges(hdc, glyphSet) fontRanges = New List(Of FontRange) count = Marshal.ReadInt32(glyphSet, 12) For i = 0 To count - 1 Dim range As FontRange = New FontRange range.Low = Marshal.ReadInt16(glyphSet, 16 + (i * 4)) range.High = range.Low + Marshal.ReadInt16(glyphSet, 18 + (i * 4)) - 1 fontRanges.Add(range) Next SelectObject(hdc, old) Marshal.FreeHGlobal(glyphSet) g.ReleaseHdc(hdc) g.Dispose() Return fontRanges End Function Public Function CheckIfCharInFont(ByVal character As Char, ByVal font As Font) As Boolean Dim intval As UInt16 = Convert.ToUInt16(character) Dim ranges As List(Of FontRange) = GetUnicodeRangesForFont(font) Dim isCharacterPresent As Boolean = False For Each range In ranges If intval >= range.Low And intval <= range.High Then isCharacterPresent = True Exit For End If Next range Return isCharacterPresent End Function

Estoy trabajando en un proyecto que genera archivos PDF que pueden contener fórmulas bastante complejas de matemáticas y ciencias. El texto se representa en Times New Roman, que tiene una cobertura Unicode bastante buena, pero no completa. Tenemos un sistema para intercambiar una fuente completa más Unicode para los puntos de código que no tienen un glifo en TNR (como la mayoría de los símbolos matemáticos "desconocidos"), pero parece que no puedo encontrar una manera de consultar el archivo * .ttf para ver si un glifo dado está presente. Hasta ahora, he codificado una tabla de búsqueda de los puntos de código que están presentes, pero preferiría una solución automática.

Estoy usando VB.Net en un sistema web bajo ASP.net, pero las soluciones en cualquier lenguaje de programación serán apreciadas.

Editar: La solución win32 se ve excelente, pero el caso específico que estoy tratando de resolver está en un sistema web ASP.Net. ¿Hay alguna manera de hacer esto sin incluir los DLL de Windows API en mi sitio web?


El código publicado por Scott Nichols es excelente, excepto por un error: si el id del glifo es mayor que Int16.MaxValue, arroja una OverflowException. Para solucionarlo, agregué la siguiente función:

Protected Function Unsign(ByVal Input As Int16) As UInt16 If Input > -1 Then Return CType(Input, UInt16) Else Return UInt16.MaxValue - (Not Input) End If End Function

Y luego cambió el bucle principal por en la función GetUnicodeRangesForFont para que se vea así:

For i As Integer = 0 To count - 1 Dim range As FontRange = New FontRange range.Low = Unsign(Marshal.ReadInt16(glyphSet, 16 + (i * 4))) range.High = range.Low + Unsign(Marshal.ReadInt16(glyphSet, 18 + (i * 4)) - 1) fontRanges.Add(range) Next


Este artículo de Microsoft KB puede ayudar: http://support.microsoft.com/kb/241020

Está un poco anticuado (fue escrito originalmente para Windows 95), pero el principio general aún puede aplicarse. El código de muestra es C ++, pero dado que solo llama a las API estándar de Windows, lo más probable es que funcione también en los lenguajes .NET con un poco de esfuerzo.

-Editar- Parece que las antiguas API de 95-era han sido obsoletas por una nueva API que Microsoft llama " Uniscribe ", que debería poder hacer lo que usted necesita.


La respuesta de Scott es buena. Aquí hay otro enfoque que probablemente sea más rápido si se comprueban solo un par de cadenas por fuente (en nuestro caso 1 cadena por fuente). Pero probablemente sea más lento si está usando una fuente para verificar toneladas de texto.

[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); /// <summary> /// 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. /// </summary> /// <param name="fontName">The name of the font to check.</param> /// <param name="text">The text to check for glyphs of.</param> /// <returns></returns> 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; }


FreeType es una biblioteca que puede leer archivos de fuentes TrueType (entre otros) y se puede utilizar para consultar la fuente de un glifo específico. Sin embargo, FreeType está diseñado para renderizar, por lo que su uso podría hacer que extraigas más código del que necesitas para esta solución.

Desafortunadamente, no existe realmente una solución clara incluso dentro del mundo de las fuentes OpenType / TrueType; la asignación de carácter a glifo tiene alrededor de una docena de definiciones diferentes según el tipo de fuente y para qué plataforma se diseñó originalmente. Puede intentar ver la definición de la tabla cmap en la copia de Microsoft de la especificación OpenType , pero no es exactamente fácil de leer.