Table and cell events to draw borders

This is a code example of iText PDF, discover more.

31st May 2016
admin-marketing

Switch code for this example

CellTitle.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * Example written by Bruno Lowagie in answer to:
  10.  * http://stackoverflow.com/questions/35746651
  11.  */
  12.  
  13. package com.itextpdf.samples.sandbox.tables;
  14.  
  15. import com.itextpdf.kernel.color.Color;
  16. import com.itextpdf.kernel.pdf.PdfDocument;
  17. import com.itextpdf.kernel.pdf.PdfWriter;
  18. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  19. import com.itextpdf.layout.Canvas;
  20. import com.itextpdf.layout.Document;
  21. import com.itextpdf.layout.element.Cell;
  22. import com.itextpdf.layout.element.Paragraph;
  23. import com.itextpdf.layout.element.Table;
  24. import com.itextpdf.layout.renderer.CellRenderer;
  25. import com.itextpdf.layout.renderer.DrawContext;
  26. import com.itextpdf.samples.GenericTest;
  27. import com.itextpdf.test.annotations.type.SampleTest;
  28.  
  29. import java.io.File;
  30.  
  31. import org.junit.experimental.categories.Category;
  32.  
  33. @Category(SampleTest.class)
  34. public class CellTitle extends GenericTest {
  35.     public static final String DEST = "./target/test/resources/sandbox/tables/cell_title.pdf";
  36.  
  37.     public static void main(String[] args) throws Exception {
  38.         File file = new File(DEST);
  39.         file.getParentFile().mkdirs();
  40.         new CellTitle().manipulatePdf(DEST);
  41.     }
  42.  
  43.     public Cell getCell(String content, String title) {
  44.         Cell cell = new Cell().add(content);
  45.         cell.setNextRenderer(new CellTitleRenderer(cell, title));
  46.         cell.setPaddingTop(8).setPaddingBottom(8);
  47.         return cell;
  48.     }
  49.  
  50.     @Override
  51.     protected void manipulatePdf(String dest) throws Exception {
  52.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  53.         Document doc = new Document(pdfDoc);
  54.         Table table = new Table(1);
  55.         Cell cell = getCell("The title of this cell is title 1", "title 1");
  56.         table.addCell(cell);
  57.         cell = getCell("The title of this cell is title 2", "title 2");
  58.         table.addCell(cell);
  59.         cell = getCell("The title of this cell is title 3", "title 3");
  60.         table.addCell(cell);
  61.         doc.add(table);
  62.         doc.close();
  63.     }
  64.  
  65.  
  66.     protected class CellTitleRenderer extends CellRenderer {
  67.         protected String title;
  68.  
  69.         public CellTitleRenderer(Cell modelElement, String title) {
  70.             super(modelElement);
  71.             this.title = title;
  72.         }
  73.  
  74.         @Override
  75.         public void drawBorder(DrawContext drawContext) {
  76.             // create above canvas in order to draw above borders (notice that we draw borders using TableRenderer)
  77.             PdfCanvas aboveCanvas = new PdfCanvas(drawContext.getDocument().getLastPage().newContentStreamAfter(),
  78.                     drawContext.getDocument().getLastPage().getResources(), drawContext.getDocument());
  79.             new Canvas(aboveCanvas, drawContext.getDocument(), getOccupiedAreaBBox())
  80.                     .add(new Paragraph(title)
  81.                             .setBackgroundColor(Color.LIGHT_GRAY)
  82.                             .setFixedPosition(getOccupiedAreaBBox().getLeft() + 5, getOccupiedAreaBBox().getTop() - 8, 30));
  83.         }
  84.     }
  85. }
CustomBorder.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * Example written by Bruno Lowagie in answer to the following question:
  10.  * http://stackoverflow.com/questions/23935566/table-borders-not-expanding-properly-in-pdf-using-itext
  11.  */
  12. package com.itextpdf.samples.sandbox.tables;
  13.  
  14. import com.itextpdf.kernel.pdf.PdfDocument;
  15. import com.itextpdf.kernel.pdf.PdfWriter;
  16. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  17. import com.itextpdf.layout.Document;
  18. import com.itextpdf.layout.border.Border;
  19. import com.itextpdf.layout.border.SolidBorder;
  20. import com.itextpdf.layout.element.Cell;
  21. import com.itextpdf.layout.element.Paragraph;
  22. import com.itextpdf.layout.element.Table;
  23. import com.itextpdf.layout.renderer.CellRenderer;
  24. import com.itextpdf.layout.renderer.DrawContext;
  25. import com.itextpdf.layout.renderer.TableRenderer;
  26. import com.itextpdf.samples.GenericTest;
  27. import com.itextpdf.test.annotations.type.SampleTest;
  28.  
  29. import org.junit.experimental.categories.Category;
  30.  
  31. import java.io.File;
  32.  
  33. @Category(SampleTest.class)
  34. public class CustomBorder extends GenericTest {
  35.     public static final String DEST = "./target/test/resources/sandbox/tables/custom_border.pdf";
  36.     public static final String TEXT = "This is some long paragraph that will be added over and over " +
  37.             "again to prove a point. It should result in rows that are split and rows that aren't.";
  38.  
  39.     public static void main(String[] args) throws Exception {
  40.         File file = new File(DEST);
  41.         file.getParentFile().mkdirs();
  42.         new CustomBorder().manipulatePdf(DEST);
  43.     }
  44.  
  45.     @Override
  46.     protected void manipulatePdf(String dest) throws Exception {
  47.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  48.         Document doc = new Document(pdfDoc);
  49.         Table table = new Table(2);
  50.         table.setWidth(500);
  51.         table.setBorder(new SolidBorder(1));
  52.         Cell cell = new Cell().add(new Paragraph(TEXT));
  53.         cell.setBorder(null);
  54.         for (int i = 0; i < 60; ) {
  55.             table.addCell(new Cell().add(new Paragraph("Cell " + (++i))).setBorder(Border.NO_BORDER));
  56.             table.addCell(new Cell().add(new Paragraph(TEXT)).setBorder(Border.NO_BORDER));
  57.         }
  58.         table.setNextRenderer(new CustomBorderTableRenderer(table, new Table.RowRange(0, 59)));
  59.         doc.add(table);
  60.  
  61.         doc.close();
  62.     }
  63. }
  64.  
  65.  
  66. class CustomBorderTableRenderer extends TableRenderer {
  67.     protected static boolean isNextPageTopToBeDrawn = false;
  68.     protected static boolean isTopToBeDrawn = true;
  69.  
  70.     public CustomBorderTableRenderer(Table modelElement, Table.RowRange rowRange) {
  71.         super(modelElement, rowRange);
  72.     }
  73.  
  74.     protected CustomBorderTableRenderer(Table modelElement) {
  75.         super(modelElement);
  76.     }
  77.  
  78.     @Override
  79.     public void drawBorder(DrawContext drawContext) {
  80.         CellRenderer[] firstRowRenderers = rows.get(0);
  81.         // yLines
  82.         PdfCanvas canvas = drawContext.getCanvas();
  83.         for (CellRenderer cellRenderer : firstRowRenderers) {
  84.             canvas.moveTo(cellRenderer.getBorderAreaBBox().getRight(),
  85.                     getBorderAreaBBox().getBottom());
  86.             canvas.lineTo(cellRenderer.getBorderAreaBBox().getRight(),
  87.                     getBorderAreaBBox().getTop());
  88.         }
  89.         // the first yLine
  90.         canvas.moveTo(firstRowRenderers[0].getBorderAreaBBox().getLeft(),
  91.                 getBorderAreaBBox().getBottom());
  92.         canvas.lineTo(firstRowRenderers[0].getBorderAreaBBox().getLeft(),
  93.                 getBorderAreaBBox().getTop());
  94.         canvas.stroke();
  95.  
  96.         for (CellRenderer[] cellRenderers : rows) {
  97.             canvas.moveTo(cellRenderers[0].getBorderAreaBBox().getLeft(),
  98.                     cellRenderers[0].getBorderAreaBBox().getBottom());
  99.             canvas.lineTo(cellRenderers[cellRenderers.length - 1].getBorderAreaBBox().getRight(),
  100.                     cellRenderers[cellRenderers.length - 1].getBorderAreaBBox().getBottom());
  101.         }
  102.         if (isTopToBeDrawn) {
  103.             canvas.moveTo(firstRowRenderers[0].getBorderAreaBBox().getLeft(),
  104.                     firstRowRenderers[0].getBorderAreaBBox().getTop());
  105.             canvas.lineTo(firstRowRenderers[firstRowRenderers.length - 1].getBorderAreaBBox().getRight(),
  106.                     firstRowRenderers[0].getBorderAreaBBox().getTop());
  107.             isTopToBeDrawn = false;
  108.         }
  109.         if (isNextPageTopToBeDrawn) {
  110.             isTopToBeDrawn = true;
  111.             isNextPageTopToBeDrawn = false;
  112.         }
  113.         canvas.stroke();
  114.     }
  115.  
  116.     @Override
  117.     public CustomBorderTableRenderer getNextRenderer() {
  118.         return new CustomBorderTableRenderer((Table) modelElement);
  119.     }
  120.  
  121.     @Override
  122.     protected TableRenderer[] split(int row) {
  123.         if (null != rows.get(row)) {
  124.             isNextPageTopToBeDrawn = true;
  125.             CellRenderer[] curRow = rows.get(row);
  126.             for (int i = 0; i < curRow.length; i++) {
  127.                 if (0 != rows.get(row)[0].getChildRenderers().size()) {
  128.                     isNextPageTopToBeDrawn = false;
  129.                     break;
  130.                 }
  131.             }
  132.         }
  133.         CustomBorderTableRenderer splitRenderer = (CustomBorderTableRenderer) createSplitRenderer(
  134.                 new Table.RowRange(rowRange.getStartRow(), rowRange.getStartRow() + row));
  135.         splitRenderer.rows = rows.subList(0, row);
  136.         CustomBorderTableRenderer overflowRenderer = (CustomBorderTableRenderer) createOverflowRenderer(
  137.                 new Table.RowRange(rowRange.getStartRow() + row, rowRange.getFinishRow()));
  138.         overflowRenderer.rows = rows.subList(row, rows.size());
  139.         splitRenderer.occupiedArea = occupiedArea;
  140.         return new TableRenderer[]{splitRenderer, overflowRenderer};
  141.     }
  142. }
CustomBorder2.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * Example written by Bruno Lowagie in answer to the following question:
  10.  * http://stackoverflow.com/questions/23935566/table-borders-not-expanding-properly-in-pdf-using-itext
  11.  */
  12. package com.itextpdf.samples.sandbox.tables;
  13.  
  14. import com.itextpdf.kernel.pdf.PdfDocument;
  15. import com.itextpdf.kernel.pdf.PdfWriter;
  16. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  17. import com.itextpdf.layout.Document;
  18. import com.itextpdf.layout.border.Border;
  19. import com.itextpdf.layout.border.SolidBorder;
  20. import com.itextpdf.layout.element.Cell;
  21. import com.itextpdf.layout.element.Paragraph;
  22. import com.itextpdf.layout.element.Table;
  23. import com.itextpdf.layout.renderer.CellRenderer;
  24. import com.itextpdf.layout.renderer.DrawContext;
  25. import com.itextpdf.layout.renderer.TableRenderer;
  26. import com.itextpdf.samples.GenericTest;
  27. import com.itextpdf.test.annotations.type.SampleTest;
  28.  
  29. import org.junit.experimental.categories.Category;
  30.  
  31. import java.io.File;
  32.  
  33. @Category(SampleTest.class)
  34. public class CustomBorder2 extends GenericTest {
  35.     public static final String DEST = "./target/test/resources/sandbox/tables/custom_border2.pdf";
  36.     public static final String TEXT = "This is some long paragraph that will be added over and over " +
  37.             "again to prove a point. It should result in rows that are split and rows that aren't.";
  38.  
  39.     public static void main(String[] args) throws Exception {
  40.         File file = new File(DEST);
  41.         file.getParentFile().mkdirs();
  42.         new CustomBorder2().manipulatePdf(DEST);
  43.     }
  44.  
  45.     @Override
  46.     protected void manipulatePdf(String dest) throws Exception {
  47.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  48.         Document doc = new Document(pdfDoc);
  49.  
  50.         Table table = new Table(2);
  51.         table.setWidth(500);
  52.         table.setBorder(new SolidBorder(1));
  53.  
  54.  
  55.         Cell cell = new Cell().add(new Paragraph(TEXT));
  56.  
  57.         cell.setBorder(null);
  58.         for (int i = 0; i < 60; ) {
  59.             table.addCell(new Cell().add("Cell " + (++i)).setBorder(Border.NO_BORDER));
  60.             table.addCell(new Cell().add(TEXT).setBorder(Border.NO_BORDER));
  61.         }
  62.         table.setNextRenderer(new CustomBorder2TableRenderer(table, new Table.RowRange(0, 59)));
  63.         doc.add(table);
  64.  
  65.         doc.close();
  66.     }
  67. }
  68.  
  69.  
  70. class CustomBorder2TableRenderer extends TableRenderer {
  71.     protected static boolean isBottomToBeDrawn = false;
  72.     protected static boolean isTopToBeDrawn = true;
  73.  
  74.     public CustomBorder2TableRenderer(Table modelElement) {
  75.         super(modelElement);
  76.     }
  77.  
  78.     public CustomBorder2TableRenderer(Table modelElement, Table.RowRange rowRange) {
  79.         super(modelElement, rowRange);
  80.     }
  81.  
  82.     @Override
  83.     public void drawBorder(DrawContext drawContext) {
  84.         CellRenderer[] firstRowRenderers = rows.get(0);
  85.         // yLines
  86.         PdfCanvas canvas = drawContext.getCanvas();
  87.         canvas.moveTo(firstRowRenderers[0].getBorderAreaBBox().getLeft(),
  88.                 getBorderAreaBBox().getBottom());
  89.         canvas.lineTo(firstRowRenderers[0].getBorderAreaBBox().getLeft(),
  90.                 getBorderAreaBBox().getTop());
  91.         canvas.moveTo(firstRowRenderers[firstRowRenderers.length - 1].getBorderAreaBBox().getRight(),
  92.                 getBorderAreaBBox().getBottom());
  93.         canvas.lineTo(firstRowRenderers[firstRowRenderers.length - 1].getBorderAreaBBox().getRight(),
  94.                 getBorderAreaBBox().getTop());
  95.  
  96.         if (isTopToBeDrawn) {
  97.             canvas.moveTo(firstRowRenderers[0].getBorderAreaBBox().getLeft(),
  98.                     firstRowRenderers[0].getBorderAreaBBox().getTop());
  99.             canvas.lineTo(firstRowRenderers[firstRowRenderers.length - 1].getBorderAreaBBox().getRight(),
  100.                     firstRowRenderers[0].getBorderAreaBBox().getTop());
  101.             isTopToBeDrawn = false;
  102.         }
  103.         if (isBottomToBeDrawn) {
  104.             canvas.moveTo(rows.get(rows.size() - 1)[0].getBorderAreaBBox().getLeft(),
  105.                     rows.get(rows.size() - 1)[0].getBorderAreaBBox().getBottom());
  106.             canvas.lineTo(
  107.                     rows.get(rows.size() - 1)[rows.get(rows.size() - 1).length - 1]
  108.                             .getBorderAreaBBox().getRight(),
  109.                     rows.get(rows.size() - 1)[rows.get(rows.size() - 1).length - 1]
  110.                             .getBorderAreaBBox().getBottom());
  111.  
  112.         }
  113.         canvas.stroke();
  114.         isBottomToBeDrawn = true;
  115.     }
  116.  
  117.     @Override
  118.     public CustomBorder2TableRenderer getNextRenderer() {
  119.         return new CustomBorder2TableRenderer((Table) modelElement);
  120.     }
  121.  
  122.     @Override
  123.     protected TableRenderer[] split(int row) {
  124.         isBottomToBeDrawn = false;
  125.         return super.split(row);
  126.     }
  127. }
CustomBorder3.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * Example written by Bruno Lowagie in answer to the following question:
  10.  * http://stackoverflow.com/questions/34555756/one-cell-with-different-border-types
  11.  */
  12. package com.itextpdf.samples.sandbox.tables;
  13.  
  14. import com.itextpdf.kernel.geom.Rectangle;
  15. import com.itextpdf.kernel.pdf.PdfDocument;
  16. import com.itextpdf.kernel.pdf.PdfWriter;
  17. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  18. import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants;
  19. import com.itextpdf.layout.Document;
  20. import com.itextpdf.layout.border.Border;
  21. import com.itextpdf.layout.element.Cell;
  22. import com.itextpdf.layout.element.Table;
  23. import com.itextpdf.layout.renderer.CellRenderer;
  24. import com.itextpdf.layout.renderer.DrawContext;
  25. import com.itextpdf.samples.GenericTest;
  26. import com.itextpdf.test.annotations.type.SampleTest;
  27.  
  28. import java.io.File;
  29.  
  30. import org.junit.experimental.categories.Category;
  31.  
  32. @Category(SampleTest.class)
  33. public class CustomBorder3 extends GenericTest {
  34.     public static final String DEST = "./target/test/resources/sandbox/tables/custom_border_3.pdf";
  35.  
  36.     public static void main(String[] args) throws Exception {
  37.         File file = new File(DEST);
  38.         file.getParentFile().mkdirs();
  39.         new CustomBorder3().manipulatePdf(DEST);
  40.     }
  41.  
  42.     @Override
  43.     protected void manipulatePdf(String dest) throws Exception {
  44.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  45.         Document document = new Document(pdfDoc);
  46.  
  47.         ILineDash solid = new Solid();
  48.         ILineDash dotted = new Dotted();
  49.         ILineDash dashed = new Dashed();
  50.  
  51.         Table table;
  52.         Cell cell;
  53.  
  54.         table = new Table(4);
  55.         table.setMarginBottom(30);
  56.         cell = new Cell().add("dotted left border");
  57.         cell.setBorder(Border.NO_BORDER);
  58.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  59.                 new ILineDash[]{null, dotted, null, null}));
  60.         table.addCell(cell);
  61.         cell = new Cell().add("solid right border");
  62.         cell.setBorder(Border.NO_BORDER);
  63.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  64.                 new ILineDash[]{null, null, null, solid}));
  65.         table.addCell(cell);
  66.         cell = new Cell().add("dashed top border");
  67.         cell.setBorder(Border.NO_BORDER);
  68.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  69.                 new ILineDash[]{dashed, null, null, null}));
  70.         table.addCell(cell);
  71.         cell = new Cell().add("bottom border");
  72.         cell.setBorder(Border.NO_BORDER);
  73.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  74.                 new ILineDash[]{null, null, solid, null}));
  75.         table.addCell(cell);
  76.         document.add(table);
  77.  
  78.         table = new Table(4);
  79.         table.setMarginBottom(30);
  80.         cell = new Cell().add("dotted left and solid top border");
  81.         cell.setBorder(Border.NO_BORDER);
  82.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  83.                 new ILineDash[]{solid, dotted, null, null}));
  84.         table.addCell(cell);
  85.         cell = new Cell().add("dashed right and dashed bottom border");
  86.         cell.setBorder(Border.NO_BORDER);
  87.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  88.                 new ILineDash[]{null, null, dashed, dashed}));
  89.         table.addCell(cell);
  90.         cell = new Cell().add("no border");
  91.         cell.setBorder(Border.NO_BORDER);
  92.         table.addCell(cell);
  93.         cell = new Cell().add("full solid border");
  94.         cell.setBorder(Border.NO_BORDER);
  95.         cell.setNextRenderer(new CustomBorder3Renderer(cell,
  96.                 new ILineDash[]{solid, solid, solid, solid}));
  97.         table.addCell(cell);
  98.         document.add(table);
  99.         document.close();
  100.     }
  101.  
  102.  
  103.     interface ILineDash {
  104.         void applyLineDash(PdfCanvas canvas);
  105.     }
  106.  
  107.  
  108.     class Solid implements ILineDash {
  109.         public void applyLineDash(PdfCanvas canvas) {
  110.         }
  111.     }
  112.  
  113.  
  114.     class Dotted implements ILineDash {
  115.         public void applyLineDash(PdfCanvas canvas) {
  116.             canvas.setLineCapStyle(PdfCanvasConstants.LineCapStyle.ROUND);
  117.             canvas.setLineDash(0, 4, 2);
  118.         }
  119.     }
  120.  
  121.  
  122.     class Dashed implements ILineDash {
  123.         public void applyLineDash(PdfCanvas canvas) {
  124.             canvas.setLineDash(3, 3);
  125.         }
  126.     }
  127.  
  128.  
  129.     class CustomBorder3Renderer extends CellRenderer {
  130.         ILineDash[] borders;
  131.  
  132.         public CustomBorder3Renderer(Cell modelElement, ILineDash[] borders) {
  133.             super(modelElement);
  134.             this.borders = new ILineDash[borders.length];
  135.             for (int i = 0; i < this.borders.length; i++) {
  136.                 this.borders[i] = borders[i];
  137.             }
  138.         }
  139.  
  140.         @Override
  141.         public void draw(DrawContext drawContext) {
  142.             super.draw(drawContext);
  143.             PdfCanvas canvas = drawContext.getCanvas();
  144.             Rectangle position = getOccupiedAreaBBox();
  145.             canvas.saveState();
  146.             if (null != borders[0]) {
  147.                 canvas.saveState();
  148.                 borders[0].applyLineDash(canvas);
  149.                 canvas.moveTo(position.getRight(), position.getTop());
  150.                 canvas.lineTo(position.getLeft(), position.getTop());
  151.                 canvas.stroke();
  152.                 canvas.restoreState();
  153.             }
  154.             if (null != borders[2]) {
  155.                 canvas.saveState();
  156.                 borders[2].applyLineDash(canvas);
  157.                 canvas.moveTo(position.getRight(), position.getBottom());
  158.                 canvas.lineTo(position.getLeft(), position.getBottom());
  159.                 canvas.stroke();
  160.                 canvas.restoreState();
  161.             }
  162.             if (null != borders[3]) {
  163.                 canvas.saveState();
  164.                 borders[3].applyLineDash(canvas);
  165.                 canvas.moveTo(position.getRight(), position.getTop());
  166.                 canvas.lineTo(position.getRight(), position.getBottom());
  167.                 canvas.stroke();
  168.                 canvas.restoreState();
  169.             }
  170.             if (null != borders[1]) {
  171.                 canvas.saveState();
  172.                 borders[1].applyLineDash(canvas);
  173.                 canvas.moveTo(position.getLeft(), position.getTop());
  174.                 canvas.lineTo(position.getLeft(), position.getBottom());
  175.                 canvas.stroke();
  176.                 canvas.restoreState();
  177.             }
  178.             canvas.stroke();
  179.             canvas.restoreState();
  180.         }
  181.     }
  182. }
DottedLineCell.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. package com.itextpdf.samples.sandbox.tables;
  9.  
  10. import com.itextpdf.kernel.geom.Rectangle;
  11. import com.itextpdf.kernel.pdf.PdfDocument;
  12. import com.itextpdf.kernel.pdf.PdfWriter;
  13. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  14. import com.itextpdf.layout.Document;
  15. import com.itextpdf.layout.border.Border;
  16. import com.itextpdf.layout.element.Cell;
  17. import com.itextpdf.layout.element.Paragraph;
  18. import com.itextpdf.layout.element.Table;
  19. import com.itextpdf.layout.renderer.CellRenderer;
  20. import com.itextpdf.layout.renderer.DrawContext;
  21. import com.itextpdf.layout.renderer.TableRenderer;
  22. import com.itextpdf.samples.GenericTest;
  23. import com.itextpdf.test.annotations.type.SampleTest;
  24.  
  25. import org.junit.experimental.categories.Category;
  26.  
  27. import java.io.File;
  28.  
  29. @Category(SampleTest.class)
  30. public class DottedLineCell extends GenericTest {
  31.     public static final String DEST = "./target/test/resources/sandbox/tables/dotted_line_cell.pdf";
  32.  
  33.     public static void main(String[] args) throws Exception {
  34.         File file = new File(DEST);
  35.         file.getParentFile().mkdirs();
  36.         new DottedLineCell().manipulatePdf(DEST);
  37.     }
  38.  
  39.     @Override
  40.     protected void manipulatePdf(String dest) throws Exception {
  41.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  42.         Document doc = new Document(pdfDoc);
  43.         doc.add(new Paragraph("Table event"));
  44.         Table table = new Table(3);
  45.         table.setNextRenderer(new DottedLineTableRenderer(table, new Table.RowRange(0, 2)));
  46.         table.addCell(new Cell().add("A1").setBorder(Border.NO_BORDER));
  47.         table.addCell(new Cell().add("A2").setBorder(Border.NO_BORDER));
  48.         table.addCell(new Cell().add("A3").setBorder(Border.NO_BORDER));
  49.         table.addCell(new Cell().add("B1").setBorder(Border.NO_BORDER));
  50.         table.addCell(new Cell().add("B2").setBorder(Border.NO_BORDER));
  51.         table.addCell(new Cell().add("B3").setBorder(Border.NO_BORDER));
  52.         table.addCell(new Cell().add("C1").setBorder(Border.NO_BORDER));
  53.         table.addCell(new Cell().add("C2").setBorder(Border.NO_BORDER));
  54.         table.addCell(new Cell().add("C3").setBorder(Border.NO_BORDER));
  55.         doc.add(table);
  56.         doc.add(new Paragraph("Cell event"));
  57.         table = new Table(1);
  58.         Cell cell = new Cell().add(new Paragraph("Test"));
  59.         cell.setNextRenderer(new DottedLineCellRenderer(cell));
  60.         cell.setBorder(Border.NO_BORDER);
  61.         table.addCell(cell.setBorder(Border.NO_BORDER));
  62.         doc.add(table);
  63.  
  64.         doc.close();
  65.     }
  66.  
  67.  
  68.     private class DottedLineTableRenderer extends TableRenderer {
  69.         public DottedLineTableRenderer(Table modelElement, Table.RowRange rowRange) {
  70.             super(modelElement, rowRange);
  71.         }
  72.  
  73.         @Override
  74.         public void drawChildren(DrawContext drawContext) {
  75.             super.drawChildren(drawContext);
  76.             PdfCanvas canvas = drawContext.getCanvas();
  77.             canvas.setLineDash(3f, 3f);
  78.             // first horizontal line
  79.             CellRenderer[] cellRenderers = rows.get(0);
  80.             canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getLeft(),
  81.                     cellRenderers[0].getOccupiedArea().getBBox().getTop());
  82.             canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight(),
  83.                     cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getTop());
  84.  
  85.             for (int i = 0; i < rows.size(); i++) {
  86.                 cellRenderers = rows.get(i);
  87.                 // horizontal lines
  88.                 canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getX(),
  89.                         cellRenderers[0].getOccupiedArea().getBBox().getY());
  90.                 canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight(),
  91.                         cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getBottom());
  92.                 // first vertical line
  93.                 Rectangle cellRect = cellRenderers[0].getOccupiedArea().getBBox();
  94.                 canvas.moveTo(cellRect.getLeft(), cellRect.getBottom());
  95.                 canvas.lineTo(cellRect.getLeft(), cellRect.getTop());
  96.                 // vertical lines
  97.                 for (int j = 0; j < cellRenderers.length; j++) {
  98.                     cellRect = cellRenderers[j].getOccupiedArea().getBBox();
  99.                     canvas.moveTo(cellRect.getRight(), cellRect.getBottom());
  100.                     canvas.lineTo(cellRect.getRight(), cellRect.getTop());
  101.                 }
  102.             }
  103.             canvas.stroke();
  104.         }
  105.     }
  106.  
  107.  
  108.     private class DottedLineCellRenderer extends CellRenderer {
  109.         public DottedLineCellRenderer(Cell modelElement) {
  110.             super(modelElement);
  111.         }
  112.  
  113.         @Override
  114.         public void draw(DrawContext drawContext) {
  115.             super.draw(drawContext);
  116.             drawContext.getCanvas().setLineDash(3f, 3f);
  117.             drawContext.getCanvas().rectangle(this.getOccupiedArea().getBBox());
  118.             drawContext.getCanvas().stroke();
  119.         }
  120.     }
  121. }
DottedLineCell2.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * Example written by Bruno Lowagie in answer to the following question:
  10.  * http://stackoverflow.com/questions/34555756/one-cell-with-different-border-types
  11.  */
  12. package com.itextpdf.samples.sandbox.tables;
  13.  
  14. import com.itextpdf.kernel.geom.Rectangle;
  15. import com.itextpdf.kernel.pdf.PdfDocument;
  16. import com.itextpdf.kernel.pdf.PdfWriter;
  17. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  18. import com.itextpdf.layout.Document;
  19. import com.itextpdf.layout.border.Border;
  20. import com.itextpdf.layout.element.Cell;
  21. import com.itextpdf.layout.element.Table;
  22. import com.itextpdf.layout.renderer.CellRenderer;
  23. import com.itextpdf.layout.renderer.DrawContext;
  24. import com.itextpdf.samples.GenericTest;
  25. import com.itextpdf.test.annotations.type.SampleTest;
  26.  
  27. import java.io.File;
  28.  
  29. import org.junit.experimental.categories.Category;
  30.  
  31. @Category(SampleTest.class)
  32. public class DottedLineCell2 extends GenericTest {
  33.     public static final String DEST = "./target/test/resources/sandbox/tables/dotted_line_cell2.pdf";
  34.  
  35.     public static void main(String[] args) throws Exception {
  36.         File file = new File(DEST);
  37.         file.getParentFile().mkdirs();
  38.         new DottedLineCell2().manipulatePdf(DEST);
  39.     }
  40.  
  41.     @Override
  42.     protected void manipulatePdf(String dest) throws Exception {
  43.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  44.         Document document = new Document(pdfDoc);
  45.         Table table;
  46.         Cell cell;
  47.  
  48.         table = new Table(4);
  49.         table.setMarginBottom(30);
  50.         cell = new Cell().add("left border");
  51.         cell.setBorder(Border.NO_BORDER);
  52.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  53.                 new boolean[]{false, true, false, false}));
  54.         table.addCell(cell);
  55.         cell = new Cell().add("right border");
  56.         cell.setBorder(Border.NO_BORDER);
  57.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  58.                 new boolean[]{false, false, false, true}));
  59.         table.addCell(cell);
  60.         cell = new Cell().add("top border");
  61.         cell.setBorder(Border.NO_BORDER);
  62.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  63.                 new boolean[]{true, false, false, false}));
  64.         table.addCell(cell);
  65.         cell = new Cell().add("bottom border");
  66.         cell.setBorder(Border.NO_BORDER);
  67.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  68.                 new boolean[]{false, false, true, false}));
  69.         table.addCell(cell);
  70.         document.add(table);
  71.  
  72.         table = new Table(4);
  73.         table.setMarginBottom(30);
  74.         cell = new Cell().add("left and top border");
  75.         cell.setBorder(Border.NO_BORDER);
  76.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  77.                 new boolean[]{true, true, false, false}));
  78.         table.addCell(cell);
  79.         cell = new Cell().add("right and bottom border");
  80.         cell.setBorder(Border.NO_BORDER);
  81.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  82.                 new boolean[]{false, false, true, true}));
  83.         table.addCell(cell);
  84.         cell = new Cell().add("no border");
  85.         cell.setBorder(Border.NO_BORDER);
  86.         table.addCell(cell);
  87.         cell = new Cell().add("full border");
  88.         cell.setBorder(Border.NO_BORDER);
  89.         cell.setNextRenderer(new DottedLineCellRenderer(cell,
  90.                 new boolean[]{true, true, true, true}));
  91.         table.addCell(cell);
  92.         document.add(table);
  93.         document.close();
  94.     }
  95. }
  96.  
  97.  
  98. class DottedLineCellRenderer extends CellRenderer {
  99.     boolean[] borders;
  100.  
  101.     public DottedLineCellRenderer(Cell modelElement, boolean[] borders) {
  102.         super(modelElement);
  103.         this.borders = new boolean[borders.length];
  104.         for (int i = 0; i < this.borders.length; i++) {
  105.             this.borders[i] = borders[i];
  106.         }
  107.     }
  108.  
  109.     @Override
  110.     public void draw(DrawContext drawContext) {
  111.         super.draw(drawContext);
  112.         PdfCanvas canvas = drawContext.getCanvas();
  113.         Rectangle position = getOccupiedAreaBBox();
  114.         canvas.saveState();
  115.         canvas.setLineDash(0, 4, 2);
  116.         if (borders[0]) {
  117.             canvas.moveTo(position.getRight(), position.getTop());
  118.             canvas.lineTo(position.getLeft(), position.getTop());
  119.         }
  120.         if (borders[2]) {
  121.             canvas.moveTo(position.getRight(), position.getBottom());
  122.             canvas.lineTo(position.getLeft(), position.getBottom());
  123.         }
  124.         if (borders[3]) {
  125.             canvas.moveTo(position.getRight(), position.getTop());
  126.             canvas.lineTo(position.getRight(), position.getBottom());
  127.         }
  128.         if (borders[1]) {
  129.             canvas.moveTo(position.getLeft(), position.getTop());
  130.             canvas.lineTo(position.getLeft(), position.getBottom());
  131.         }
  132.         canvas.stroke();
  133.         canvas.restoreState();
  134.     }
  135. }
DottedLineHeader.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. package com.itextpdf.samples.sandbox.tables;
  9.  
  10. import com.itextpdf.kernel.geom.Rectangle;
  11. import com.itextpdf.kernel.pdf.PdfDocument;
  12. import com.itextpdf.kernel.pdf.PdfWriter;
  13. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  14. import com.itextpdf.layout.Document;
  15. import com.itextpdf.layout.Style;
  16. import com.itextpdf.layout.border.Border;
  17. import com.itextpdf.layout.element.Cell;
  18. import com.itextpdf.layout.element.Paragraph;
  19. import com.itextpdf.layout.element.Table;
  20. import com.itextpdf.layout.renderer.CellRenderer;
  21. import com.itextpdf.layout.renderer.DrawContext;
  22. import com.itextpdf.layout.renderer.TableRenderer;
  23. import com.itextpdf.samples.GenericTest;
  24. import com.itextpdf.test.annotations.type.SampleTest;
  25.  
  26. import org.junit.experimental.categories.Category;
  27.  
  28. import java.io.File;
  29.  
  30. @Category(SampleTest.class)
  31. public class DottedLineHeader extends GenericTest {
  32.     public static final String DEST = "./target/test/resources/sandbox/tables/dotted_line_header.pdf";
  33.  
  34.     public static void main(String[] args) throws Exception {
  35.         File file = new File(DEST);
  36.         file.getParentFile().mkdirs();
  37.         new DottedLineHeader().manipulatePdf(DEST);
  38.     }
  39.  
  40.     @Override
  41.     protected void manipulatePdf(String dest) throws Exception {
  42.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  43.         Document doc = new Document(pdfDoc);
  44.  
  45.         Table table = new Table(3);
  46.         table.setNextRenderer(new DottedHeaderTableRenderer(table, new Table.RowRange(0, 1)));
  47.         Style noBorder = new Style().setBorder(Border.NO_BORDER);
  48.         table.addHeaderCell(new Cell().add("A1").addStyle(noBorder));
  49.         table.addHeaderCell(new Cell().add("A2").addStyle(noBorder));
  50.         table.addHeaderCell(new Cell().add("A3").addStyle(noBorder));
  51.         table.addCell(new Cell().add("B1").addStyle(noBorder));
  52.         table.addCell(new Cell().add("B2").addStyle(noBorder));
  53.         table.addCell(new Cell().add("B3").addStyle(noBorder));
  54.         table.addCell(new Cell().add("C1").addStyle(noBorder));
  55.         table.addCell(new Cell().add("C2").addStyle(noBorder));
  56.         table.addCell(new Cell().add("C3").addStyle(noBorder));
  57.         doc.add(table);
  58.         doc.add(new Paragraph("Cell event"));
  59.         table = new Table(3);
  60.         Cell cell = new Cell().add(new Paragraph("A1")).addStyle(noBorder);
  61.         cell.setNextRenderer(new DottedHeaderCellRenderer(cell));
  62.         table.addCell(cell);
  63.         cell = new Cell().add(new Paragraph("A2")).addStyle(noBorder);
  64.         cell.setNextRenderer(new DottedHeaderCellRenderer(cell));
  65.         table.addCell(cell);
  66.         cell = new Cell().add(new Paragraph("A3")).addStyle(noBorder);
  67.         cell.setNextRenderer(new DottedHeaderCellRenderer(cell));
  68.         table.addCell(cell);
  69.         table.addCell(new Cell().add("B1").addStyle(noBorder));
  70.         table.addCell(new Cell().add("B2").addStyle(noBorder));
  71.         table.addCell(new Cell().add("B3").addStyle(noBorder));
  72.         table.addCell(new Cell().add("C1").addStyle(noBorder));
  73.         table.addCell(new Cell().add("C2").addStyle(noBorder));
  74.         table.addCell(new Cell().add("C3").addStyle(noBorder));
  75.         doc.add(table);
  76.  
  77.         doc.close();
  78.     }
  79.  
  80.  
  81.     private class DottedHeaderTableRenderer extends TableRenderer {
  82.         public DottedHeaderTableRenderer(Table modelElement, Table.RowRange rowRange) {
  83.             super(modelElement, rowRange);
  84.         }
  85.  
  86.         @Override
  87.         public void drawChildren(DrawContext drawContext) {
  88.             super.drawChildren(drawContext);
  89.             PdfCanvas canvas = drawContext.getCanvas();
  90.             canvas.setLineDash(3f, 3f);
  91.             Rectangle headersArea = headerRenderer.getOccupiedArea().getBBox();
  92.             canvas.moveTo(headersArea.getLeft(), headersArea.getTop());
  93.             canvas.lineTo(headersArea.getRight(), headersArea.getTop());
  94.  
  95.             canvas.moveTo(headersArea.getLeft(), headersArea.getBottom());
  96.             canvas.lineTo(headersArea.getRight(), headersArea.getBottom());
  97.             canvas.stroke();
  98.         }
  99.     }
  100.  
  101.  
  102.     private class DottedHeaderCellRenderer extends CellRenderer {
  103.         public DottedHeaderCellRenderer(Cell modelElement) {
  104.             super(modelElement);
  105.         }
  106.  
  107.         @Override
  108.         public void draw(DrawContext drawContext) {
  109.             super.draw(drawContext);
  110.             PdfCanvas canvas = drawContext.getCanvas();
  111.             canvas.setLineDash(3f, 3f);
  112.             canvas.moveTo(this.getOccupiedArea().getBBox().getLeft(), this.getOccupiedArea().getBBox().getBottom());
  113.             canvas.lineTo(this.getOccupiedArea().getBBox().getRight(),
  114.                     this.getOccupiedArea().getBBox().getBottom());
  115.             canvas.moveTo(this.getOccupiedArea().getBBox().getLeft(),
  116.                     this.getOccupiedArea().getBBox().getTop());
  117.             canvas.lineTo(this.getOccupiedArea().getBBox().getRight(),
  118.                     this.getOccupiedArea().getBBox().getTop());
  119.             canvas.stroke();
  120.         }
  121.     }
  122. }
RoundedCorners.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * This example was written by Bruno Lowagie in answer to the following questions:
  10.  * http://stackoverflow.com/questions/30106862/left-and-right-top-round-corner-for-rectangelroundrectangle
  11.  */
  12. package com.itextpdf.samples.sandbox.tables;
  13.  
  14. import com.itextpdf.kernel.pdf.PdfDocument;
  15. import com.itextpdf.kernel.pdf.PdfWriter;
  16. import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
  17. import com.itextpdf.layout.Document;
  18. import com.itextpdf.layout.element.Cell;
  19. import com.itextpdf.layout.element.Paragraph;
  20. import com.itextpdf.layout.element.Table;
  21. import com.itextpdf.layout.renderer.CellRenderer;
  22. import com.itextpdf.layout.renderer.DrawContext;
  23. import com.itextpdf.samples.GenericTest;
  24. import com.itextpdf.test.annotations.type.SampleTest;
  25.  
  26. import org.junit.experimental.categories.Category;
  27.  
  28. import java.io.File;
  29.  
  30. @Category(SampleTest.class)
  31. public class RoundedCorners extends GenericTest {
  32.     public static final String DEST = "./target/test/resources/sandbox/tables/rounded_corners.pdf";
  33.  
  34.     public static void main(String[] args) throws Exception {
  35.         File file = new File(DEST);
  36.         file.getParentFile().mkdirs();
  37.         new RoundedCorners().manipulatePdf(DEST);
  38.     }
  39.  
  40.     @Override
  41.     protected void manipulatePdf(String dest) throws Exception {
  42.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  43.         Document doc = new Document(pdfDoc);
  44.  
  45.         Table table = new Table(3);
  46.         Cell cell = getCell("These cells have rounded borders at the top.");
  47.         table.addCell(cell);
  48.         cell = getCell("These cells aren't rounded at the bottom.");
  49.         table.addCell(cell);
  50.         cell = getCell("A custom cell event was used to achieve this.");
  51.         table.addCell(cell);
  52.         doc.add(table);
  53.  
  54.         doc.close();
  55.     }
  56.  
  57.     public Cell getCell(String content) {
  58.         Cell cell = new Cell().add(new Paragraph(content));
  59.         cell.setNextRenderer(new RoundedCornersCellRenderer(cell));
  60.         cell.setPadding(5);
  61.         cell.setBorder(null);
  62.         return cell;
  63.     }
  64.  
  65.  
  66.     private class RoundedCornersCellRenderer extends CellRenderer {
  67.         public RoundedCornersCellRenderer(Cell modelElement) {
  68.             super(modelElement);
  69.         }
  70.  
  71.         @Override
  72.         public void draw(DrawContext drawContext) {
  73.             float llx = getOccupiedAreaBBox().getX() + 2;
  74.             float lly = getOccupiedAreaBBox().getY() + 2;
  75.             float urx = getOccupiedAreaBBox().getX() + getOccupiedAreaBBox().getWidth() - 2;
  76.             float ury = getOccupiedAreaBBox().getY() + getOccupiedAreaBBox().getHeight() - 2;
  77.             float r = 4;
  78.             float b = 0.4477f;
  79.             PdfCanvas canvas = drawContext.getCanvas();
  80.             canvas.moveTo(llx, lly);
  81.             canvas.lineTo(urx, lly);
  82.             canvas.lineTo(urx, ury - r);
  83.             canvas.curveTo(urx, ury - r * b, urx - r * b, ury, urx - r, ury);
  84.             canvas.lineTo(llx + r, ury);
  85.             canvas.curveTo(llx + r * b, ury, llx, ury - r * b, llx, ury - r);
  86.             canvas.lineTo(llx, lly);
  87.             canvas.stroke();
  88.             super.draw(drawContext);
  89.         }
  90.     }
  91. }
TableBorder.java
  1. /*
  2.  
  3.     This file is part of the iText (R) project.
  4.     Copyright (c) 1998-2016 iText Group NV
  5.  
  6. */
  7.  
  8. /**
  9.  * Example written by Bruno Lowagie in answer to the following question:
  10.  * http://stackoverflow.com/questions/35340003
  11.  */
  12. package com.itextpdf.samples.sandbox.tables;
  13.  
  14. import com.itextpdf.kernel.geom.Rectangle;
  15. import com.itextpdf.kernel.pdf.PdfDocument;
  16. import com.itextpdf.kernel.pdf.PdfWriter;
  17. import com.itextpdf.layout.Document;
  18. import com.itextpdf.layout.border.Border;
  19. import com.itextpdf.layout.element.Cell;
  20. import com.itextpdf.layout.element.Table;
  21. import com.itextpdf.layout.renderer.DrawContext;
  22. import com.itextpdf.layout.renderer.TableRenderer;
  23. import com.itextpdf.samples.GenericTest;
  24. import com.itextpdf.test.annotations.type.SampleTest;
  25.  
  26. import java.io.File;
  27.  
  28. import org.junit.experimental.categories.Category;
  29.  
  30. @Category(SampleTest.class)
  31. public class TableBorder extends GenericTest {
  32.     public static final String DEST = "./target/test/resources/sandbox/tables/tables_border.pdf";
  33.  
  34.     public static void main(String[] args) throws Exception {
  35.         File file = new File(DEST);
  36.         file.getParentFile().mkdirs();
  37.         new TableBorder().manipulatePdf(DEST);
  38.     }
  39.  
  40.     @Override
  41.     protected void manipulatePdf(String dest) throws Exception {
  42.         PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
  43.         Document doc = new Document(pdfDoc);
  44.         Table table = new Table(4);
  45.         for (int aw = 0; aw < 16; aw++) {
  46.             table.addCell(new Cell().add("hi").setBorder(Border.NO_BORDER));
  47.         }
  48.         // Notice that one should set renderer after table completion
  49.         table.setNextRenderer(new TableBorderRenderer(table));
  50.         doc.add(table);
  51.         doc.close();
  52.     }
  53.  
  54.  
  55.     class TableBorderRenderer extends TableRenderer {
  56.         public TableBorderRenderer(Table modelElement) {
  57.             super(modelElement);
  58.         }
  59.  
  60.         @Override
  61.         protected void drawBorders(DrawContext drawContext) {
  62.             Rectangle rect = getOccupiedAreaBBox();
  63.             drawContext.getCanvas()
  64.                     .saveState()
  65.                     .rectangle(rect.getLeft(), rect.getBottom(), rect.getWidth(), rect.getHeight())
  66.                     .stroke()
  67.                     .restoreState();
  68.         }
  69.     }
  70. }
Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now