Monthly Archives: October 2007

PrivateFontCollection (¿Font Embedding?)

0
Filed under .NET Development

Como no podía ser de otra manera el .NET Framework nos trae la clase PrivateFontCollection que pertenece al nombre de espacio System.Drawing.Text que sirve para cargar fuentes en nuestra aplicación sin necesidad de que se encuentren instaladas en el sistema. La clase tiene dos métodos principales:

AddFontFile – Agrega una fuente del archivo especificado a esta colección PrivateFontCollection.
AddMemoryFont – Agrega una fuente incluida en la memoria del sistema a esta colección PrivateFontCollection.

El ejemplo que voy a mostrar a continuación utiliza el método AddMemoryFont y trabaja con la clase Marshal (o es lo mismo decir que los programadores Visual Basic .NET van a poder convertirlo fácilmente ya que no utilizo “unsafe”).

Marshal (Clase):

Proporciona una colección de métodos para asignar memoria no administrada, copiar bloques de memoria no administrados y convertir los tipos administrados en no administrados, así como otros métodos diversos que se utilizan al interactuar con código no administrado.

        PrivateFontCollection _PrivateFontCollection = new PrivateFontCollection();
        private void AddEmbeddedFontToPrivateFontCollection(string pManifestResourceName)
        {
            using (Stream lFontEmbeddedResource = Assembly.GetExecutingAssembly().GetManifestResourceStream(pManifestResourceName))
            {
                byte[] lFontData = new byte[lFontEmbeddedResource.Length];
                lFontEmbeddedResource.Read(lFontData, 0, lFontData.Length);
                IntPtr lUnmanagedMemoryPointer = Marshal.AllocHGlobal(lFontData.Length);
                Marshal.Copy(lFontData, 0, lUnmanagedMemoryPointer, lFontData.Length);
                _PrivateFontCollection.AddMemoryFont(lUnmanagedMemoryPointer, lFontData.Length);
                Marshal.FreeHGlobal(lUnmanagedMemoryPointer);
            }
        }

        private void Form_Load(object sender, EventArgs e)
        {
            AddEmbeddedFontToPrivateFontCollection("WindowsApplication.AlienMushrooms.ttf");
            if (_PrivateFontCollection.Families.Length > 0)
            {
                FontFamily lFontFamily = _PrivateFontCollection.Families[0];
                if (lFontFamily.IsStyleAvailable(FontStyle.Regular))
                {
                    Font lFont = new Font(lFontFamily, 48, FontStyle.Regular);
                    this.label1.Font = lFont;
                }
            }
            this.label1.Text = ".NET Framework";
        }

_PrivateFontCollection es una variable que está declarada a nivel de modulo. Esto es algo muy importante que tenemos que tener en cuenta dependiendo de lo que vayamos a hacer (recuerden que las variables que se encuentran declaradas a nivel de modulo tienen un tiempo de vida hasta que la ejecución del programa finaliza), de lo contrario podemos obtener excepciones como: AccessViolationException (Attempted to read or write protected memory. This is often an indication that other memory is corrupt.)

Llamando al método IsStyleAvailable de la clase FontFamily nos estamos asegurando que la fuente tenga el estilo que queremos representar, de lo contrario se producirá una excepción.

Algunos se estarán preguntando ¿de qué sirve todo esto? Lo que se me ocurre en este momento a modo de ejemplo es un sitio Web que tiene que generar un CAPTCHA con una fuente especial pero nuestro sitio Web va a estar alojado en un servidor Web que no es nuestro y por consiguiente puede o no tener la fuente que queremos utilizar para generarlo.