How to cross out a table cell using pdfHtml and iText 7

I’m trying to display a crossed-out table cell.
I’ve tried dozens of different approaches.
My best solution was using four linear-gradients, one for each corner (because there is no support for transparent backgrounds).
enter image description here

The issue here is, that I have to specify the height of the table cell, thus when the text in any other cell in the same row has more lines than expected, the cross is no longer from corner to corner.

enter image description here

I’ve also tried using a background-image with background-size set to 100% 100%. However, pdfHtml does not support background-size.
I’ve tried multiple workarounds that work in Chrome, but none work in pdfHtml.

Does anybody know a (possible) solution?

Thanks,
–Zuzu_Typ–

Answer

pdfHTML eventually utilizes iText’s layout mechanism which is quite flexible. You can achieve your end goal by customizing the rendering logic for a cell and plug that implementation into pdfHTML.

First off, custom cell renderer:

private static class CustomCellRenderer extends CellRenderer {
    public CustomCellRenderer(Cell modelElement) {
        super(modelElement);
    }

    @Override
    public IRenderer getNextRenderer() {
        return new CustomCellRenderer((Cell) modelElement);
    }

    @Override
    public void drawBackground(DrawContext drawContext) {
        super.drawBackground(drawContext);
        PdfCanvas canvas = drawContext.getCanvas();
        Rectangle area = getOccupiedAreaBBox();
        canvas.moveTo(area.getLeft(), area.getTop()).lineTo(area.getRight(), area.getBottom());
        canvas.moveTo(area.getLeft(), area.getBottom()).lineTo(area.getRight(), area.getTop());
        canvas.stroke();
    }
}

Essentially, we have reused the default implementation and extended it with drawing a line from bottom left corner to the right top one and from the top left one to the bottom right corner.

Now, we need to use the custom renderer for layout objects that are created in pdfHTML. They are created in tag workers, so customizing a tag worker for a table cell:

private static class CustomTdTagWorker extends TdTagWorker {
    public CustomTdTagWorker(IElementNode element,
            ProcessorContext context) {
        super(element, context);
    }

    @Override
    public IPropertyContainer getElementResult() {
        IPropertyContainer cell = super.getElementResult();
        if (cell instanceof Cell) {
            ((Cell) cell).setNextRenderer(new CustomCellRenderer((Cell) cell));
        }
        return cell;
    }
}

The missing piece is that we need to configure pdfHTML to use our custom tag worker for <td> cells and the way to do so it to create a custom tag worker factory:

private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
    @Override
    public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
        if (TagConstants.TD.equals(tag.name())) {
            return new CustomTdTagWorker(tag, context);
        }
        return super.getCustomTagWorker(tag, context);
    }
}

The only missing piece is to pass the custom tag worker factory to pdfHTML itself and this is done via converter properties:

HtmlConverter.convertToPdf(inFile, outFile, new ConverterProperties().setTagWorkerFactory(new CustomTagWorkerFactory()));

With the code above for the following HTML:

<html>
<head>
    <style>
        td, th {
            border: solid 1px;
        }
    table {
      border-collapse: collapse;
    }
    </style>
</head>
<body>
<table>
  <tbody>
    <tr>
    <td>Cell 1</td>
    <td>Cell 2</td>
   </tr>
   <tr>
    <td>Another cell 1</td>
    <td>Another cell 2</td>
   </tr>
  </tbody>
  <tfoot>
    <td>
      Footer 1
    </td>
    <td>
      Footer 2
    </td>
  </tfoot>
</table>
</body>
</html>

I got the following visual result after converting to PDF:

result

Leave a Reply

Your email address will not be published. Required fields are marked *