2012-05-17 133 views
14

puedo insertar texto simple como esto:¿Cómo puedo crear párrafos de ancho fijo 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(); 

pero ¿cómo puedo crear un párrafo similar a HTML con el atributo de anchura?

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

Respuesta

18

Según this answer No es posible insertar saltos de línea en un texto y tener PDF visualizar correctamente (si el uso de PDFBox o algo más), por lo que creo auto-envolver un poco de texto para encajar en alguna anchura puede también ser algo que no puede hacer automáticamente. (además, hay muchas maneras de envolver un texto, solo palabras completas, dividirlas en partes más pequeñas, etc.)

This answer a otra pregunta (sobre el centrado de una cadena) da algunos consejos sobre cómo hacerlo usted mismo. Suponiendo que escribió una función possibleWrapPoints(String):int[] para enumerar todos los puntos en el texto de un ajuste de línea puede suceder (excluyendo "cero", como "la longitud del texto"), una posible solución podría ser:

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 ejemplo de possibleWrapPoints, que permitir envolver en cualquier punto que no es parte de una palabra (reference), podría ser:

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

actualización: algo de información adicional:

  • El formato de archivo PDF se diseñó para tener el mismo aspecto en diferentes situaciones, la funcionalidad como la que solicitó tiene sentido en un editor/creador de PDF, pero no en el archivo PDF per se. Por esta razón, la mayoría de las herramientas de "bajo nivel" tienden a concentrarse en lidiar con el formato de archivo en sí y dejan cosas así.

  • Herramientas de nivel superior OTOH generalmente tiene medios para hacer esta conversión. Un ejemplo es Platypus (para Python, sin embargo), que do tiene formas sencillas de crear párrafos, y se basa en las funciones de nivel inferior ReportLab para hacer la representación de PDF real. No conozco herramientas similares para PDFBox, pero this post da algunos consejos sobre cómo convertir contenido HTML a PDF en un entorno Java, utilizando herramientas disponibles gratuitamente. No los he probado yo mismo, pero estoy publicando aquí porque podría ser útil (en caso de que mi intento hecho a mano arriba no sea suficiente).

+1

En PDF, es posible hacer un salto de línea. (Ver [mi respuesta] (http://stackoverflow.com/a/15205956/1016477)) – Lukas

4

He estado trabajando combinando la respuesta de Lukas con mgibsonbr y he llegado a esto. Más útil para las personas que buscan una solución lista para usar, creo.

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

} 
Cuestiones relacionadas