Diferencias entre el renderizado de fuentes Swing y iText

Estoy creando una aplicación que, entre otras cosas, permite al usuario insertar un texto en un PDF, usando una capa.

La posición del texto en la página PDF se puede establecer usando la aplicación, que representa el PDF usando ICEPdf dentro de un JPanel. Después de seleccionar la posición y el tamaño de la capa, la aplicación la procesa en PDF usando iText (v. 5.3.2).

El problema al que me enfrento es que la representación de la fuente de Swing es visiblemente diferente del resultado final en el PDF.

Aquí hay algunas capturas de pantalla, ambas utilizando la fuente simple Helvetica dentro del mismo cuadro delimitador:

Renderizar un texto con Swing:

protected void paintComponent(Graphics g){
      //for each line...
      g.drawString(text, b0, b1);
      //b0 and b1 are computed from the selected bounding box for the text
}

Tengo esto:

Renderizado de swing

Renderizar un texto con iText:

PdfTemplate t; //PdfTemplate is created elsewhere
ColumnText ct = new ColumnText(t);
ct.setRunDirection(PdfWriter.RUN_DIRECTION_NO_BIDI);
ct.setSpaceCharRatio(1);
ct.setSimpleColumn(new Phrase(text, font), b0, b1, b3, b4, font.getSize(), Element.ALIGN_BOTTOM); 
//b0, b1, b2 and b3 are the bounding box of the text
ct.go();

Tengo esto:

Representación de PDF

Entonces, la pregunta es: ¿qué se puede hacer para hacer que Swing e iText representen las fuentes exactamente de la misma manera? Puedo ajustar Swing o iText, así que no importa qué código se modifique, necesito una verdadera experiencia WYSIWYG para el usuario.

Intenté con otras fuentes y tipos, pero aún hay algunas diferencias entre ellos. Creo que me falta alguna configuración.

Gracias.

Respuesta 1

Editar:

La fuente en Java se mide en píxeles, pero iText mide en puntos, y sabemos que hay 72 puntos por pulgada, y para una máquina con Windows estándar hay 96 píxeles por pulgada / ppp.

Primero necesitamos encontrar la diferencia entre un punto y un píxel:

difference = 72 / dpi
      0.75 = 72 / 96

A continuación, podemos multiplicar el tamaño de fuente Java con la diferencia para obtener el tamaño de fuente iText, si el tamaño de fuente java es 16, entonces el tamaño de fuente iText debería ser 12 cuando se usa con 96 ppp.

iTextFontSize = difference x javaFontSize
           12 = 0.75 x 16

En una máquina Windows, 96 ppp suele ser la norma, pero recuerde que no siempre es así, debe resolverlo para cada máquina diferente.


Publicación original

Creo que la diferencia es causada por dar pistas.

Solución 1:

La mejor manera de hacerlo sería dibujar todo en una imagen almacenada. Luego, la imagen en búfer se dibuja en el componente de oscilación y la misma imagen en búfer se dibuja exactamente en el PDF, de esa manera no debería haber diferencia entre ellos.

Idea alternativa:

Otra idea que puede no funcionar tan bien, pero funcionará mejor con su código existente es dibujar el contenido del componente swing directamente en una imagen almacenada en un búfer y luego dibujar la imagen almacenada en el PDF.

El siguiente es un ejemplo rápido que dibujará el contenido de un JPanel en una imagen almacenada en búfer con algunas sugerencias de representación diferentes. (Cambie las sugerencias para adaptarse a su componente de swing)

public BufferedImage createImage(JPanel panel)
{
    BufferedImage swingComponent = new BufferedImage(
            panel.getHeight(), panel.getWidth(), 
            BufferedImage.TYPE_INT_RGB);

    Graphics2D g = swingComponent.createGraphics();

    g.setRenderingHint(RenderingHints.KEY_RENDERING,
                       RenderingHints.VALUE_RENDER_QUALITY);

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                       RenderingHints.VALUE_ANTIALIAS_ON);

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                       RenderingHints.VALUE_INTERPOLATION_BILINEAR);

    g.dispose();
    return swingComponent; //print this to your PDF
}
Respuesta: 2

En java spec 17.3 Sleep and Yield 17.3 Sleep and Yield Thread.sleep hace que el hilo que se está ejecutando actualmente se suspenda (cese temporal de la ejecución) durante el tiempo especificado, sujeto al ...

Recientemente cambié el script gwt.xml para compilar solo 1 permutación (es decir, solo 8), esto resuelve mi problema anterior, sin embargo, surge un problema cosmético, que es una ventana emergente molesta que aparece cada vez ...

Estoy tratando de crear una función que compare todos los elementos de una matriz con todos los elementos de una segunda matriz y devolverá todas las coincidencias posibles, y un mensaje si no se encuentran coincidencias. Cuando trato de ...

Estoy tratando de obtener campos de datos específicos de la API Java de Bloomberg. Veo en la guía de desarrolladores que puedo extraer algunos campos con: Request request = refDataSvc.createRequest ("...