2012-09-28 12 views
6

Per generare un documento PDF/X valido, è obbligatorio includere tutti i tipi di carattere. In qualche modo non è possibile per me usare quei font in un contesto di Graphics2D.Come utilizzare i font incorporati per chiamare Graphics2D.drawString (...) con iText (DefaultFontMapper?)

Questo Unittests mostra il problema (righe di commento sono alcuni test che ho fatto):

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(); 
    } 

} 

Si genera un PdfXConformanceException con il messaggio: ". Tutti i tipi di carattere devono essere incorporati Questo non è: Helvetica.

ho già passato in rassegna anche se la classe PdfGraphics2D per verificare l'attuazione setFont() e ho scoperto, che sarà utilizzato un FontMapper. ho già aggiunto questo al unittest sopra.

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; 
    } 
} 

L'Unittest è basato su this example dal libro di iText in Action. Here sono alcuni altri esempi di FontMapper.

Per eseguire l'unittest è necessario questa dipendenza: ("" che si trova in)

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

il carattere personalizzato a trovare here.

uscita

La console mostra me questo (per identificare la fontName):

Comicate: ./COMICATE.TTF 

risposta

2

non sono sicuro del modo esatto per correggere l'errore nel codice, ma ci sono facili soluzioni:

Soluzione alternativa 1) Creare un'Immagine Bufferata per eseguire tutte le operazioni di grafica su. Quindi puoi utilizzare tutte le normali funzioni java.awt.Graphics come drawString e setColor indipendentemente da iText, e quando hai finito basta disegnare l'immagine in un PDF. AVVERTENZA fate qualità libera del testo quando lo zoom, ma qui è un esempio:

//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); 

Soluzione 2) Questo utilizza funzionalità iText per disegnare stringhe, senza la necessità di creare oggetti grafici, il tipo di carattere è curata utilizzando un BaseFont come segue:

//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(); 

so che questo non dà la risposta che stavate cercando, se si sta solo disegnando una piccola quantità di testo poi aggirare 2 opere grandi, ho usato qualcosa di simile a soluzione 2 prima. Se questo non aiuta, sono sicuro che Bruno avrà la risposta.

+0

Ciao, grazie per il suggerimento. Purtroppo non posso farvi ricorso a soluzioni alternative :(. Non sono io a chiamare g2d.drawText (...), è JFreechart. – d0x

1

Definendo nuovi BaseFont (s) e implementando l'interfaccia di FontMapper() >>> public BaseFont awtToPdf (carattere java.awt.Font). Questo applicherà il awt.font (s) come incorporato nel pdf.

Nell'esempio seguente, "stampa" g2D (incluso il metodo "drawString"), disegnato nella classe esterna. Il risultato è un pdf vettoriale esportato con font "ArialMT" e "Arial-BoldMT" incorporati.

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

l'unica soluzione funzionante per la creazione di un PDF con 'itext', posizionando i file .tff all'interno del Jar eseguibile – AntJavaDev

Problemi correlati