java - Apache FOP Mostrando### con SimSun
apache-fop chinese-locale (1)
Se deben seguir tres pasos para que los caracteres chinos se muestren correctamente en un archivo PDF creado con FOP (esto también es cierto para todos los caracteres que no están disponibles en la fuente predeterminada y, en general, para usar una fuente no predeterminada) .
Usemos este sencillo ejemplo para mostrar las advertencias producidas por FOP cuando algo está mal:
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="one">
<fo:region-body />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="one">
<fo:flow flow-name="xsl-region-body">
<!-- a block of chinese text -->
<fo:block>博洛尼亚大学中国学生的毕业论文</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
Al procesar esta entrada, FOP ofrece varias advertencias similares a esta:
org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "?" (0x535a) not available in font "Helvetica".
...
Sin ninguna indicación explícita de la familia de fuentes en el archivo FO, FOP usa de forma predeterminada Helvetica, que es una de las fuentes Base-14 (fuentes que están disponibles en todas partes, por lo que no es necesario incrustarlas).
Cada fuente admite un conjunto de caracteres, asignándoles glifos visibles; cuando una fuente no admite un carácter, se genera la advertencia anterior y el PDF muestra "#" en lugar del glifo faltante .
Paso 1: establezca font-family en el archivo FO
Si la fuente predeterminada no admite los caracteres de nuestro texto
(o simplemente queremos usar una fuente diferente)
, debemos usar la propiedad de
font-family
para indicar la deseada.
El valor de
font-family
se hereda, por lo que si queremos usar la misma fuente para todo el documento, podemos establecer la propiedad en
fo:page-sequence
;
si necesitamos una fuente especial solo para algunos párrafos o palabras, podemos establecer
font-family
en el
fo:block
o
fo:inline
relevante.
Entonces, nuestra entrada se convierte (usando una fuente que tengo como ejemplo):
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="one">
<fo:region-body />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="one">
<fo:flow flow-name="xsl-region-body">
<!-- a block of chinese text -->
<fo:block font-family="SimSun">博洛尼亚大学中国学生的毕业论文</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
¡Pero ahora recibimos una nueva advertencia, además de las antiguas!
org.apache.fop.events.LoggingEventListener processEvent
WARNING: Font "SimSun,normal,400" not found. Substituting with "any,normal,400".
org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "?" (0x535a) not available in font "Times-Roman".
...
FOP no sabe cómo asignar "SimSun" a un archivo de fuente , por lo que su valor predeterminado es una fuente genérica Base-14 (Times-Roman) que no admite nuestros caracteres chinos, y el PDF aún muestra "#" .
Paso 2: configure la asignación de fuentes en el archivo de configuración de FOP
Dentro de la carpeta de FOP, el archivo
conf/fop.xconf
es una configuración de ejemplo;
podemos editarlo directamente o hacer una copia para comenzar.
El archivo de configuración es un archivo XML, y tenemos que agregar las
asignaciones de fuentes
dentro de
/fop/renderers/renderer[@mime = ''application/pdf'']/fonts/
(hay una sección de
renderer
para cada posible tipo de mime de salida, por lo que compruebe que está insertando su mapeo en el correcto):
<?xml version="1.0"?>
<fop version="1.0">
...
<renderers>
<renderer mime="application/pdf">
...
<fonts>
<!-- specific font mapping -->
<font kerning="yes" embed-url="/Users/furini/Library/Fonts/SimSun.ttf" embedding-mode="subset">
<font-triplet name="SimSun" style="normal" weight="normal"/>
</font>
<!-- "bulk" font mapping -->
<directory>/Users/furini/Library/Fonts</directory>
</fonts>
...
</renderer>
...
</renderers>
</fop>
-
cada elemento de
font
apunta a un archivo de fuente -
cada entrada de
font-triplet
identifica una combinación defont-family
font-style
+font-style
(normal, cursiva, ...) +font-weight
(normal, negrita, ...) asignada al archivo de fuente en el elementofont
primario -
usando elementos de
folder
también es posible configurar automáticamente todos los archivos de fuentes dentro de las carpetas indicadas (pero esto lleva algún tiempo si las carpetas contienen muchas fuentes)
Si tenemos un conjunto de archivos completo con versiones específicas de la fuente deseada (normal, cursiva, negrita, clara, negrita cursiva, ...) podemos asignar cada archivo al triplete de fuente preciso, produciendo así un PDF muy sofisticado.
En el extremo opuesto del espectro podemos asignar todo el triplete al mismo archivo de fuente, si es todo lo que tenemos disponible: en la salida, todo el texto aparecerá igual, incluso si en el archivo FO partes del mismo se marcaron en cursiva o negrita.
Tenga en cuenta que no necesitamos registrar todos los tripletes de fuentes posibles; si falta uno, FOP usará la fuente registrada para una "similar" (por ejemplo, si no asignamos el triplete "SimSun, cursiva, 400" FOP usará la fuente asignada a "SimSun, normal, 400" , advirtiéndonos sobre la sustitución de fuentes).
Todavía no hemos terminado, ya que sin el siguiente y último paso nada cambia cuando procesamos nuestro archivo de entrada.
Paso 3: dile a FOP que use el archivo de configuración
Si llamamos a FOP desde la línea de comandos, usamos la opción
-c
para apuntar a nuestro archivo de configuración, por ejemplo:
$ fop -c /path/to/our/fop.xconf input.fo input.pdf
Desde el código java podemos usar (ver también el sitio de FOP ):
fopFactory.setUserConfig(new File("/path/to/our/fop.xconf"));
Ahora, por fin, el PDF debería usar correctamente las fuentes deseadas y aparecer como se esperaba.
Si en cambio, FOP termina abruptamente con un error como este:
org.apache.fop.cli.Main startFOP
SEVERE: Exception org.apache.fop.apps.FOPException: Failed to resolve font with embed-url ''/Users/furini/Library/Fonts/doesNotExist.ttf''
significa que FOP no pudo encontrar el archivo de fuente, y la configuración de la fuente debe verificarse nuevamente; causas típicas son
- un error tipográfico en la fuente url
- privilegios insuficientes para acceder al archivo de fuente
Mantengo un programa que utiliza Apache FOP para imprimir documentos PDF. Ha habido un par de quejas sobre los caracteres chinos que aparecen como "####". Encontré un hilo existente sobre este problema y realicé algunas investigaciones de mi parte.
http://apache-fop.1065347.n5.nabble.com/Chinese-Fonts-td10789.html
Tengo los archivos de idioma uming.tff instalados en mi sistema. A diferencia de la persona en este hilo, todavía obtengo el "####".
A partir de este momento, ¿alguien ha visto una solución que le permita imprimir caracteres complejos en un documento PDF con Apache FOP?
Ryan