itextpdf-writer

Is it possible to access PdfWriter or PdfContentByte when given iTextSharp.text.Document alone?


My question is exactly as the title says.

The reason I ask this question is that I need to workaround a wrong design. Simply speaking, my task is to implement the body of a callback function. The callback function receives a single argument of iTextSharp.text.Document and other non-iTextSharp data. The callback function will then add content (image, text, etc.) to the Document. It does not receive a PdfWriter or PdfContentByte argument. The callback function will not be able to ask its caller for anything else.

According to the Chapter 1.3.2 of the book "iText in Action", the iTextSharp.text.Document object allows one to add high-level objects to the PDF, whereas PdfWriter or its underlying PdfContentByte would be needed if anyone needs to add low-level content.

The design mistake was that the previous software design requirement only specifies the need to add content which are covered by the high-level objects. Now the requirement has changed; I have to add low-level content as well. However, the callback interface was based on the previous requirement and was not changeable (due to semi-technical issues).

In particular, I have to apply setRGBColorFillF on some content. This is the reason I need access to the low-level writer.

My detailed question is therefore:

From my reading of other Stackoverflow question, neither is possible. However, because of the difficulty for asking to change the interface, I thought it would be prudent for me to ask once again.


Remark 1.

(For those who insist on knowing the difficulty of changing the interface, the mis-designed interface is already in-the-wild, and therefore any future change means that clients using the previous interface will be missing the feature (the content that is added by the callback function) if the callback implementation requires a correctly-designed interface.)


Remark 2.

I am aware of the correct way to get the PdfContentByte, as in this answer. I also blame myself for suggesting the wrong interface to another project team much earlier in the process without fully realizing what is meant in the five steps described in the Chapter 1.3 "Creating a PDF document in five steps".


Solution

  • Let me explain some of the history of iText.

    When I initially wrote iText, it was my intention to create a library that was able to create PDF documents and that allowed developers to create PDF without having to bother about PDF syntax.

    To achieve this, I introduced the distinction between the Document class and the PdfWriter class. The Document class wasn't supposed to be aware that PDF was being created, it was only to be used to add content such as Paragraphs, Lists, and other high-level objects for content. The PdfWriter was responsible for translating all this content into PDF.

    However: PDF isn't a trivial document format, and I was faced with an annoying problem: if something went wrong during the creation of the PDF document, I ended up with an incomplete PDF file and it was very hard to debug such a file, because you often don't have a clue what caused the problem if you only have half of a PDF file.

    So I also introduced an HtmlWriter (later on, other people also created an RtfWriter). The concept was simple: you would create a Document instance and you would attach one or more listeners to this Document. You could add one or more PdfWriter instances, one or more HtmlWriter instances, etc.

    In recent versions of iText, HtmlWriter and RtfWriter have been removed from the library, but the concept remains: the writer listens to the document, and there is no way the document knows how many (if any) writer is listening.

    This is the long version of my answer to your question.

    The short version is No, it is not possible to access a PdfWriter instance when you only have a Document instance.