2012-09-28 36 views
6

Para generar un documento PDF/X válido, es obligatorio tener todas las fuentes incrustadas. De alguna manera no me es posible usar esas fuentes en un contexto Graphics2D.Cómo usar fuentes incrustadas para llamar a Graphics2D.drawString (...) con iText (DefaultFontMapper?)

Este unittests muestra el problema (líneas comentadas son algunas pruebas que hice):

import java.awt.Font; 
import java.awt.Graphics2D; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.PrintStream; 
import java.util.Map.Entry; 

import org.junit.Test; 

import com.itextpdf.awt.DefaultFontMapper; 
import com.itextpdf.awt.DefaultFontMapper.BaseFontParameters; 
import com.itextpdf.awt.PdfGraphics2D; 
import com.itextpdf.text.Document; 
import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.Rectangle; 
import com.itextpdf.text.pdf.PdfWriter; 

public class TestFont 
{ 

    @Test 
    public void shouldBeAbleToAddFountsAndDrawOnCanvas() throws FileNotFoundException, DocumentException 
    { 
     final DefaultFontMapper mapper = new DefaultFontMapper(); 
     mapper.insertDirectory("."); 

     final PrintStream out2 = new PrintStream(System.out); 
     for (final Entry<String, BaseFontParameters> entry : mapper.getMapper().entrySet()) 
     { 
      out2.println(String.format("%s: %s", entry.getKey(), entry.getValue().fontName)); 
     } 
     out2.flush(); 

     final float width = 150; 
     final float height = 150; 

     final Document document = new Document(new Rectangle(width, height)); 
     final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("fonts.pdf")); 
     writer.setPDFXConformance(PdfWriter.PDFX32002); 

     document.open(); 
     final Graphics2D g2d = new PdfGraphics2D(writer.getDirectContent(), width, height, mapper); 

     g2d.setFont(new Font("Comicate", Font.PLAIN, 12)); 

     g2d.drawString("Hello world", 5, 24); 

     g2d.dispose(); 

     document.close(); 
    } 

} 

Se generará un PdfXConformanceException con el mensaje: ". Todas las fuentes deben estar incrustadas Éste no es: Helvetica.

ya pesar de que me levantase la clase PdfGraphics2D para comprobar la aplicación setFont() y descubrí, que se utilizará un FontMapper. ya añade esto a la unittest anteriormente.

public void setFont(Font f) { 
    if (f == null) 
     return; 
    if (onlyShapes) { 
     font = f; 
     return; 
    } 
    if (f == font) 
     return; 
    font = f; 
    fontSize = f.getSize2D(); 
    baseFont = getCachedBaseFont(f); 
} 

private BaseFont getCachedBaseFont(Font f) { 
    synchronized (baseFonts) { 
     BaseFont bf = (BaseFont)baseFonts.get(f.getFontName()); 
     if (bf == null) { 
      bf = fontMapper.awtToPdf(f); 
      baseFonts.put(f.getFontName(), bf); 
     } 
     return bf; 
    } 
} 

Unittest se basa en this example del libro iText in Action. Here son algunos otros ejemplos sobre FontMapper.

Para ejecutar el unittest necesita esta dependencia: ("" ubicado en)

<dependency> 
    <groupId>com.itextpdf</groupId> 
    <artifactId>itextpdf</artifactId> 
    <version>5.3.2</version> 
</dependency> 

la fuente personalizada a encontrar here.

salida

La consola muestra mí esto (para identificar el fontName):

Comicate: ./COMICATE.TTF 

Respuesta

2

No estoy seguro de la manera exacta para corregir el error en el código, pero hay soluciones fáciles:

Solución 1) Cree una Imagen Buffered para hacer todos sus gráficos de pintura. Luego puede usar todas las funciones normales java.awt.Graphics como drawString y setColor independientemente de iText, y cuando termine simplemente dibuje la imagen en un PDF. Advertencia le hace perder calidad de texto al utilizar el zoom, pero aquí es un ejemplo:

//create doccument and writer  
Rectangle pagesize = new Rectangle(200, 100); 
Document document= new Document(pagesize); 
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf")); 

BufferedImage bf = new BufferedImage(BorderWidth, BorderHeight, BorderWidth); 
//Do all graphics code here, draw strings and images etc 
    //Some code to set font (java.awt.Font) 
    //Some code to draw string 
    //Some code to draw image? 

//Convert BufferedImage to Image 
Image img = (Image)bf; 
//draw image to PDF using writer 
writer.getDirectContentUnder().addImage(img); 

Solución 2) Este utiliza características iText para dibujar cadenas, sin necesidad de crear objetos gráficos, la fuente es atendido mediante el uso de un BaseFont de la siguiente manera:

//create doccument and writer  
Rectangle pagesize = new Rectangle(200, 100); 
Document document= new Document(pagesize); 
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf")); 

document.open(); 
//This sample uses the "GOTHIC.TTF" font file located in the "Template" package 
BaseFont bf = BaseFont.createFont(GUI.class.getClass().getResource("/Template/GOTHIC.TTF") + "", BaseFont.WINANSI, BaseFont.EMBEDDED); 

//set font type, size and color 
Font font = new Font(bf, 13.5f); 

PdfContentByte canvas = writer.getDirectContent(); 

canvas.beginText(); 
canvas.setFontAndSize(bf, 10); 
//Method Usage: showTextAligned(Align, String, x, y, rotation); 
canvas.showTextAligned(Element.ALIGN_TOP, "My Text Here", 75, 40, 0); 
canvas.endText(); 

document.close(); 

sé que esto no da la respuesta que estabas buscando, sin embargo, si usted está dibujando una pequeña cantidad de texto a continuación, la solución 2 funciona bien, he usado algo similar a la solución 2 antes de. Si esto no ayuda, entonces estoy seguro de que Bruno tendrá la respuesta.

+0

Hola, gracias por tu sugerencia. Tristemente no puedo hacer uso de tus soluciones :(. No soy yo quien llama al g2d.drawText (...), es JFreechart. – d0x

1

Al definir nuevos BaseFont (s) y al implementar la interfaz de FontMapper() >>> public BaseFont awtToPdf (java.awt.Font font). Esto aplicará las awt.font (s) como incrustadas en el pdf.

En el siguiente ejemplo, "imprimo" g2D (incluido el método "drawString"), dibujado en la clase externa. El resultado es exportado vector pdf con fuentes "ArialMT" y "Arial-BoldMT" incrustadas solamente.

preview img

PdfWriter pdfWriter = null; 
    try { 
     pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(file)); 
     document.open(); 
     BaseFont fontRegular = BaseFont.createFont("C:\\Windows\\Fonts\\arial_0.ttf", "Cp1251", BaseFont.EMBEDDED); 
     BaseFont fontBold = BaseFont.createFont("C:\\Windows\\Fonts\\arialbd_0.ttf", "Cp1251", BaseFont.EMBEDDED); 
     FontMapper fontMapper = new FontMapper() { 

      @Override 
      public java.awt.Font pdfToAwt(BaseFont arg0, int arg1) { 
       // TODO Auto-generated method stub 
       return null; 
      } 

      @Override 
      public BaseFont awtToPdf(java.awt.Font font) { 
       if (font.equals(Fonts.getFontRegular10()) || font.equals(Fonts.getFontRegular12())){ 
        return fontRegular; 
       } 
       else { 
        return fontBold; 
       } 
      } 
     }; 
     PdfContentByte cb = pdfWriter.getDirectContent(); 
     PdfTemplate template = cb.createTemplate(MainFrame.getFRAME_WIDTH(), MainFrame.getFRAME_HEIGHT()); 
     Graphics2D g2D = new PdfGraphics2D(template, MainFrame.getFRAME_WIDTH(), MainFrame.getFRAME_HEIGHT(), fontMapper); 
     MainFrame.getPanel().print(g2D); 
     g2D.dispose(); 
     cb.addTemplate(template, 0, 0); 
    } 
    catch (Exception e1) { 
     e1.printStackTrace(); 
    } 
    finally { 
     document.close(); 
    } 
+0

la única solución de trabajo para crear un PDF con 'itext', colocando los archivos .tff dentro del tarro ejecutable – AntJavaDev

Cuestiones relacionadas