iText é uma biblioteca Java para manipulação de documentos em PDF (Portable Document Format). PDF é um formato de arquivo aberto (ISO-32000-1), originalmente criado pela Adobe. O iText é livre e de código-fonte aberto sob a licença Affero General Public License (AGPL). Atualmente existem duas versões do iText: uma versão para Java e outra versão para C#, esta última chamada de iTextSharp. Essa poderosa ferramenta pode ser usada para criar relatórios em pdf, além de uma variedade de outras coisas como ingressos digitais para companhias aéreas ou shows, boletos, e muito mais. iText também pode ser integrado com uma aplicação para gerar documentos PDF como um alternativa à papéis impressos para adicionar assinaturas digitais nos documentos. Outra funcionalidade é a possibilidade de concatenar ou separar diferentes documentos.

Nota: Caso o leitor queira se aprofundar mais nos estudos sobre iText, esse artigo mostra uma Introdução ao iText

Nas próximas seções veremos melhor alguns dos blocos básicos de construção utilizados no iText, esses objetos são considerados como sendo de alto nível. Esses objetos permitem que possamos gerar documentos PDF sem nos preocuparmos com a sintaxe do PDF.

Na Figura 1 temos um diagrama simplificado dos objetos básicos de construções e os seus relacionamentos.

Figura 1. Diagrama UML com os relacionamentos e principais atributos dos blocos básicos de construção do iText.

No restante do artigo conceitualizaremos e exemplificaremos os seguintes blocos básicos de construção utilizados no iText: Chunk e Phrase. Os blocos Paragraph, List, ListItem, Anchor, Chapter, Section, e Image serão vistos nos próximos artigos.

Chunk

Um Chunk (Pedaço) é a menor parte significativa de texto que pode ser adicionado em um Document. O objeto Chunk contém um StringBuffer que representa um pedaço de texto onde todos os caracteres possuem a mesma fonte, tamanho, estilo e cor. Essas propriedades são definidas num objeto Font.

Outras propriedades do Chunk, tais como a cor do fundo, a elevação do texto e os valores sublinhados são definidos como atributos.

Segue na Listagem 1 um exemplo utilizando o objeto Chunk.

Listagem 1. Exemplo utilizando o objeto Chunk.


  import java.io.FileOutputStream;
  import java.io.IOException;
   
  import com.itextpdf.text.BaseColor;
  import com.itextpdf.text.Chunk;
  import com.itextpdf.text.Document;
  import com.itextpdf.text.DocumentException;
  import com.itextpdf.text.Font;
  import com.itextpdf.text.Font.FontFamily;
  import com.itextpdf.text.pdf.PdfWriter;
   
   
  public class ExemploChunk {
   
         public static final String RESULT = 
         "C:\\Users\\higor\\Desktop\\proj_iText\\arqPDFexemplo.pdf";
   
         public static void main(String[] args) 
         throws DocumentException, IOException {
               Document document = new Document();
               PdfWriter.getInstance(document, 
                new FileOutputStream(RESULT))
                .setInitialLeading(16);
               document.open();
               
               adicionaDocumento(document, "Brasil", "1");
               adicionaDocumento(document, "Argentina", "2");
   
               document.close();
         }
         
         private static void adicionaDocumento(Document document, 
         String pais, String id) throws DocumentException {
               document.add(new Chunk(pais));
               document.add(new Chunk(" "));
               Font font = new Font(
                             FontFamily.HELVETICA, 6, Font.BOLD, 
                            BaseColor.WHITE);
               Chunk id_chunk = new Chunk(id, font);
               id_chunk.setBackground(BaseColor.BLACK, 1f, 0.5f, 1f, 1.5f);
               id_chunk.setTextRise(6);
               document.add(id_chunk);
               document.add(Chunk.NEWLINE);
         }
         
  }

Na Figura 2 vemos o resultado da execução do exemplo acima.

Figura 2. Resultado da execução da Listagem 1.

Na segunda linha dentro do método main temos o comando "PdfWriter.getInstance(document, new FileOutputStream(RESULT)).setInitialLeading(16);". O método "setInitialLeading(16)" indica o espaço necessário entre duas linhas. Como um exercício o leitor poderia experimentar retirar esse método e conferir como fica o pdf gerado. Pode-se verificar uma sobreposição na posição vertical, setando novamente o leading tem-se uma distância vertical entre as linhas.

No método adicionaDocumento na terceira linha temos a definição das fontes do nosso Chunk com a fonte HELVETICA, negrito e com a cor da fonte branca. Na quinta linha o nosso fundo foi pintado de preto com o método setBackground(), esse método desenha um retângulo colorido atrás do texto contido no Chunk. Os outros parâmetros definem espaços extras para a esquerda, para baixo, direta e topo do objeto Chunk. Por fim Chunk.NEWLINE faz com que uma linha seja pulada para baixo.

Normalmente o objeto Chunk será utilizado para compor outros objetos de texto como os objetos Phrases e Paragraphs. Na maioria dos casos não adicionaremos objetos Chunk diretamente para um Document, exceto para alguns Chunks especiais como Chunk.NEWLINE.

Phrase

Um objeto Phrase é como uma lista de Chunks, ou uma sequência de palavras. Uma boa prática é criarmos constantes para diferentes fontes. O exemplo da Listagem 2 ilustra isso.

Listagem 2. Exemplo de utilização do objeto Phrase.


  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.UnsupportedEncodingException;
   
  import com.itextpdf.text.Chunk;
  import com.itextpdf.text.Document;
  import com.itextpdf.text.DocumentException;
  import com.itextpdf.text.Font;
  import com.itextpdf.text.Font.FontFamily;
  import com.itextpdf.text.Phrase;
  import com.itextpdf.text.pdf.PdfWriter;
   
   
  public class ExemploPhrase {
   
         public static final String RESULT = 
         "C:\\Users\\higor\\Desktop\\proj_iText\\arqPDFexemplo4.pdf";
         
         public static final Font BOLD_UNDERLINED = 
         new Font(FontFamily.TIMES_ROMAN, 12, 
          Font.BOLD | Font.UNDERLINE);
   
         public static final Font NORMAL = new Font
         (FontFamily.TIMES_ROMAN, 12);
   
         public static Phrase createDirectorPhrase
          (byte[] pais, boolean mostraVirgula)
                      throws UnsupportedEncodingException {
   
               Phrase director = new Phrase();
               director.add(new Chunk(new String(pais, "UTF-8"),
                BOLD_UNDERLINED)); //UTF-8 é opicional
               
               if (mostraVirgula)
                      director.add(new Chunk(",", BOLD_UNDERLINED));
               
               director.add(new Chunk(" ", NORMAL));
   
               return director;
         }
   
         public static void main(String[] args) 
         throws DocumentException, IOException {
               Document document = new Document();
               PdfWriter.getInstance(document, 
                new FileOutputStream(RESULT));
               document.open();
   
               byte[] brArray = new byte[] {'B','r','a','s','i','l'};
               byte[] arArray = new byte[] 
                {'A','r','g','e','n','t','i','n','a'};
               
               
               document.add(createDirectorPhrase(brArray, true));
               document.add(createDirectorPhrase(arArray, false));
   
               document.close();
         }
         
         
  }

Na Figura 3 vemos o resultado da execução do exemplo acima.

Figura 3. Resultado da execução da Listagem 2.

Outra funcionalidade interessante que o iText nos oferece é a possibilidade de importarmos uma fonte. Para isso usamos um BaseFont. O exemplo da Listagem 3 mostra como isso poderia ser feito.

Listagem 3. Exemplo do uso de fontes externas.


  public static final Font BOLD;
  public static final Font NORMAL;
   
  static {
           BaseFont timesbd = null;
           BaseFont times = null;
   
           try {
                   timesbd = BaseFont.createFont
                    ("c:/windows/fonts/timesbd.ttf",
                    BaseFont.WINANSI, BaseFont.EMBEDDED);
   
                   times = BaseFont.createFont
                    ("c:/windows/fonts/times.ttf",
                    BaseFont.WINANSI, BaseFont.EMBEDDED);
   
           } catch (DocumentException e) {
                     e.printStackTrace();
                     System.exit(1);
           } catch (IOException e) {
                     e.printStackTrace();
                     System.exit(1);
           }
   
           BOLD = new Font(timesbd, 12);
           NORMAL = new Font(times, 12);
  }

Com isso, poderíamos usar o BOLD e o NORMAL em nosso código.

Uma boa prática quando queremos uma nova linha no documento é nunca usarmos diretamente o comando “document.add(Chunk.NEWLINE);” e sim o comando “document.add(new Chunk("\n", NORMAL));”. Quando utilizamos diretamente o comando “document.add(Chunk.NEWLINE);” a nova linha será dada através da fonte atual do texto. Utilizamos o segundo comando a nova linha seguirá sempre o tamanho de uma fonte normal.

Com isso, neste artigo vimos uma introdução aos blocos básicos de construção utilizados no iText. No total temos nove blocos de construção bastante utilizados, são eles: Chunk, Phrase, Paragraph, List, ListItem, Anchor, Chapter, Section, e Image. Neste artigo conceitualizamos e exemplificamos os blocos básicos de construção Chunk e Phrase. Com a utilização desses dois blocos já podemos fazer muitas coisas com o iText, uma ferramenta bastante poderosa. Nos próximos artigos, conforme solicitado pelos leitores, veremos os demais blocos de construção disponibilizamos no iText.

Bibliografia

[1] Eclipse Foundation Tutorial, disponível em http://www.eclipse.org/tutorial

[2] LOWAGIE, B. iText in Action, Second Edition. Manning, 2011.

[3] iText PDF Library. Disponível em http://sourceforge.net/projects/itext/