2012-05-17 14 views
14

posso inserire testo semplice come questo:Come posso creare paragrafi a larghezza fissa con PDFbox?

document = new PDDocument(); 
page = new PDPage(PDPage.PAGE_SIZE_A4); 
document.addPage(page); 
PDPageContentStream content = new PDPageContentStream(document, page); 
content.beginText(); 
content.moveTextPositionByAmount (10 , 10); 
content.drawString ("test text"); 
content.endText(); 
content.close(); 

ma come posso creare un paragrafo simile in HTML usando l'attributo width?

<p style="width:200px;">test text</p> 

risposta

18

Secondo this answer Non è possibile inserire interruzioni di riga in un testo e avere visualizzare PDF in modo corretto (se l'utilizzo PDFBox o altro), quindi credo che auto-wrapping del testo per adattarsi in qualche larghezza può anche essere qualcosa che non può fare automaticamente (Inoltre, ci sono molti modi per avvolgere un testo - solo parole intere, spezzarle in parti più piccole, ecc.)

This answer a un'altra domanda (sul centraggio di una stringa) fornisce alcuni suggerimenti su come farlo da soli. Supponendo che hai scritto una funzione possibleWrapPoints(String):int[] per elencare tutti i punti nel testo un involucro parola può accadere (esclusi "zero", tra cui "lunghezza del testo"), una possibile soluzione potrebbe essere:

PDFont font = PDType1Font.HELVETICA_BOLD; // Or whatever font you want. 
int fontSize = 16; // Or whatever font size you want. 
int paragraphWidth = 200; 
String text = "test text"; 

int start = 0; 
int end = 0; 
int height = 10; 
for (int i : possibleWrapPoints(text)) { 
    float width = font.getStringWidth(text.substring(start,i))/1000 * fontSize; 
    if (start < end && width > paragraphWidth) { 
     // Draw partial text and increase height 
     content.moveTextPositionByAmount(10 , height); 
     content.drawString(text.substring(start,end)); 
     height += font.getFontDescriptor().getFontBoundingBox().getHeight()/1000 * fontSize; 
     start = end; 
    } 
    end = i; 
} 
// Last piece of text 
content.moveTextPositionByAmount(10 , height); 
content.drawString(text.substring(start)); 

Un esempio di possibleWrapPoints, che consentire il confezionamento in qualsiasi punto che non è parte di una parola (reference), potrebbe essere:

int[] possibleWrapPoints(String text) { 
    String[] split = text.split("(?<=\\W)"); 
    int[] ret = new int[split.length]; 
    ret[0] = split[0].length(); 
    for (int i = 1 ; i < split.length ; i++) 
     ret[i] = ret[i-1] + split[i].length(); 
    return ret; 
} 

Aggiornamento: alcune informazioni aggiuntive:

  • Il formato file PDF è stato progettato per apparire uguale in situazioni diverse, funzionalità come quella richiesta ha senso in un editor/creatore PDF, ma non nel file PDF di per sé. Per questo motivo, la maggior parte degli strumenti "di basso livello" tendono a concentrarsi sull'affrontare il formato di file stesso e lasciare cose del genere.

  • Strumenti di livello superiore OTOH di solito ha i mezzi per effettuare questa conversione. Un esempio è Platypus (per Python, però), che do ha un modo semplice per creare paragrafi e fa affidamento sulle funzioni di livello inferiore ReportLab per eseguire il rendering PDF effettivo. Non sono a conoscenza di strumenti simili per PDFBox, ma lo this post fornisce alcuni suggerimenti su come convertire il contenuto HTML in PDF in un ambiente Java, utilizzando strumenti disponibili gratuitamente. Non li ho provati da solo, ma sto postando qui poiché potrebbe essere utile (nel caso in cui il mio tentativo fatto a mano sopra non sia abbastanza).

+1

In PDF è possibile effettuare un'interruzione di riga. (vedi [la mia risposta] (http://stackoverflow.com/a/15205956/1016477)) – Lukas

4

Ho lavorato combinando la risposta Lukas con mgibsonbr e sono arrivato a questo. Più utile per le persone che cercano una soluzione pronta all'uso, penso.

private void write(Paragraph paragraph) throws IOException { 
    out.beginText(); 
    out.appendRawCommands(paragraph.getFontHeight() + " TL\n"); 
    out.setFont(paragraph.getFont(), paragraph.getFontSize()); 
    out.moveTextPositionByAmount(paragraph.getX(), paragraph.getY()); 
    out.setStrokingColor(paragraph.getColor()); 

    List<String> lines = paragraph.getLines(); 
    for (Iterator<String> i = lines.iterator(); i.hasNext();) { 
     out.drawString(i.next().trim()); 
     if (i.hasNext()) { 
      out.appendRawCommands("T*\n"); 
     } 
    } 
    out.endText(); 

} 

public class Paragraph { 

    /** position X */ 
    private float x; 

    /** position Y */ 
    private float y; 

    /** width of this paragraph */ 
    private int width = 500; 

    /** text to write */ 
    private String text; 

    /** font to use */ 
    private PDType1Font font = PDType1Font.HELVETICA; 

    /** font size to use */ 
    private int fontSize = 10; 

    private int color = 0; 

    public Paragraph(float x, float y, String text) { 
     this.x = x; 
     this.y = y; 
     this.text = text; 
    } 

    /** 
    * Break the text in lines 
    * @return 
    */ 
    public List<String> getLines() throws IOException { 
     List<String> result = Lists.newArrayList(); 

     String[] split = text.split("(?<=\\W)"); 
     int[] possibleWrapPoints = new int[split.length]; 
     possibleWrapPoints[0] = split[0].length(); 
     for (int i = 1 ; i < split.length ; i++) { 
      possibleWrapPoints[i] = possibleWrapPoints[i-1] + split[i].length(); 
     } 

     int start = 0; 
     int end = 0; 
     for (int i : possibleWrapPoints) { 
      float width = font.getStringWidth(text.substring(start,i))/1000 * fontSize; 
      if (start < end && width > this.width) { 
       result.add(text.substring(start,end)); 
       start = end; 
      } 
      end = i; 
     } 
     // Last piece of text 
     result.add(text.substring(start)); 
     return result; 
    } 

    public float getFontHeight() { 
     return font.getFontDescriptor().getFontBoundingBox().getHeight()/1000 * fontSize; 
    } 

    public Paragraph withWidth(int width) { 
     this.width = width; 
     return this; 
    } 

    public Paragraph withFont(PDType1Font font, int fontSize) { 
     this.font = font; 
     this.fontSize = fontSize; 
     return this; 
    } 

    public Paragraph withColor(int color) { 
     this.color = color; 
     return this; 
    } 

    public int getColor() { 
     return color; 
    } 

    public float getX() { 
     return x; 
    } 

    public float getY() { 
     return y; 
    } 

    public int getWidth() { 
     return width; 
    } 

    public String getText() { 
     return text; 
    } 

    public PDType1Font getFont() { 
     return font; 
    } 

    public int getFontSize() { 
     return fontSize; 
    } 

}