Uno de los aspectos más peliagudos (o exigentes) en la creación de documentos PDF es todo lo relacionado con el texto… y especialmente la tipografía que puedas (o no) utilizar de entre todas las fuentes instaladas en tu equipo (lo cual puede ser desde las instaladas por omisión ¡a varios cientos de ellas!)
Por omisión, el estándar PDF observa un total de 14 tipografías que puedes utilizar libremente sin que estas se incorporen como parte del documento propiamente dicho (es decir, sin que se incluyan los datos de las propias tipografías).
Esto garantiza algo muy importante: cualquier usuario al que envíes el documento PDF podrá abrirlo y verlo tal cual fue creado, sin que el texto sufra de ningún tipo de variación o sustitución de fuentes y todo lo malo derivado de ello: pérdida de estilos, variaciones en los valores de tracking y kerning, etc.
¿Cuál es el conjunto de fuentes del estándar PDF?
Times-Roman Times-Bold Time-Italic Time-BoldItalic Courier Courier Courier-Bold Courier-Oblique Helvetica Helvetica-Bold Helvetica-Oblique Helvetica-BoldOblique Symbol ZapfDingbats
Y para simplificar su uso hemos incluido una Enumeración como parte de la clase PDFDocument. De modo que si, por ejemplo, quieres utilizar la variación Times-Bold, entonces sólo necesitarás utilizar estas dos líneas de código:
g.FontName = PDFDocument.StandardFontNames.Times g.Bold = true
Además, y para no aumentar innecesariamente el tamaño del documento PDF, el uso de este conjunto de fuentes ¡también tiene la virtud de acelerar mucho las cosas en la creación de los documentos PDF!
Más allá del Standard 14
Pero muy probablemente querrás utilizar cualquiera de las tipografías instaladas por omisión en tu sistema operativo… o bien aquellas que hayas añadido tu mismo a la carpeta Fuentes.
En ese caso, las cosas empiezan a ponerse algo más complicadas; porque para poder “dibujarlas” como una representación vectorial como parte de tu documento PDF, el estándar PDF necesita conocer por adelantado una serie de información sobre las tipografías utilizadas: ancho de los glifos, valores mínimo y máximo de kerning, las variaciones de estilo soportadas… y esto se complica aun más cuando también has de soportar varias tecnologías de tipos.
Por tanto, esto significa que la clase PDFDocument ¡necesita explorar cada una de las fuentes que puedas utilizar en tu documento para que estas se rendericen correctamente! (y esto implica inspeccionar ciertamente una GRAN cantidad de datos).
Para aliviar en la medida de lo posible un proceso tan arduo, la clase PDFDocument ya utiliza varias técnicas para acelerar las cosas lo máximo posible sobre todas las fuentes que puedas tener instaladas (además, ten en cuenta que muchas veces esto también implica profundizar en la jerarquía de carpetas dentro de la carpeta Fuentes del sistema).
Por ejemplo, una de estas técnicas (y por otro lado, la más evidente) consiste en inspeccionar una fuente sólo cuando sea realmente necesario… lo que significa que esto tendrá lugar sólo cuando utilices una fuente determinada por primera vez, cacheando toda la información requerida para posteriores accesos. Además, también pre-cachea el nombre de todas las fuentes que puedas tener instaladas en la carpeta Fuentes del sistema operativo… de modo que pueda “encontrarla” más rápidamente una vez que estés listos para utilizarla en tu documento.
Estas dos, en combinación con otras técnicas, garantiza que la creación inicial de una instancia PDFDocument y el dibujado de texto se realice lo más rápido posible para una cantidad “razonable” de fuentes instaladas en tu equipo (e incluso no tan “razonable”).
Una diferencia importante cuando se utilizan fuentes más allá de las comprendidas en el Estándar 14 es que nadie puede garantizar que los destinatarios de los documentos PDF tendrás las mismas fuentes instaladas en sus equipos (incluyendo, además las posibles diferencias existentes entre variaciones para un mismo nombre de fuente)… ¡lo que resultaría en un “desastre de renderizado de texto”!
De modo que, para garantizar que el texto de tus documentos PDF se renderice correctamente, sin importar cuántas fuentes vayas a utilizar a la hora de componerlo, se incluyen todos los datos necesarios de las fuentes utilizadas como parte del documento PDF propiamente dicho (es decir, se embeben las fuentes). De este modo, y con el pequeño precio de incluir los datos de las fuentes usadas como parte del documento, no importará si el destinatario del documento tiene dichas fuentes instaladas o no en su equipo, el documento PDF se renderizará y verá correctamente tal y como fue creado.
No importa cuantas veces vayas a utilizar la misma fuente en tu documento, la referencia (y, por tanto, los datos de la fuente) sólo se incluirán una vez.
Acelerando las cosas
Además, puede darse el caso de que estés interesado en trabajar sólo con un subgrupo de todas las fuentes que puedas tener instaladas en tu disco (o además de estas, ¡como por ejemplo las que hayas incluido como parte de tu propia app o solución!)
Si ese es el caso, entonces puedes utilizar el método PDFDocument.AddFonts
pasando como parámetro una instancia de FolderItem que apunte a la carpeta que contenga los archivos de fuentes que quieras utilizar. Sólo has de asegurarte de utilizar este método antes de utilizar cualquiera de las fuentes contenidas en la carpeta.
De igual modo, esto también acelerará el proceso de inspección de fuentes aun más dado que el PDF buscará la fuente requerida sólo entre los archivos añadidos mediante el método AddFonts
. (Puedes utilizar el método PDFDocument.AddFonts
apuntando a diferentes grupos de fuentes tantas veces como necesites.)
Por ejemplo, pongamos por caso que tienes una carpeta en el escritorio con un tal de 20 archivos de fuentes en su interior; de modo que mediante el siguiente código de ejemplo se creará un documento PDF “Catálogo de Fuentes” cuyo contenido será un total de 20 líneas formadas por una muestra de texto fija seguida del nombre de la fuente:
Var f As FolderItem = SpecialFolder.Desktop.Child("Fonts Catalog") PDFDocument.AddFonts(f) Var fName As String Var pdfDoc As New PDFDocument Var g As Graphics = pdfDoc.Graphics Var offset As Integer = 20 Var textSample As String = "Text Sample with Font: " For n As Integer = 0 To 20 fName = f.ChildAt(n).Name.NthField(".",1) g.FontName = fName g.FontSize = 10 g.DrawText(textSample + fName, 20, offset) offset = offset + 10 + g.FontAscent Next Var target As FolderItem = SpecialFolder.Desktop.Child("FontSample.pdf") pdfDoc.Save(target) target.Open
En este caso, la siguiente captura de pantalla muestra el documento PDF resultante del ejemplo:
El tamaño total del documento PDF son unos meros 700 KB en disco, con la garantía de que cualquiera a quien se lo envíes podrá verlo correctamente porque los datos de las fuentes están incorporados como parte del documento propiamente dicho.