pythonpdfborb

Unable to place text on a rectangle object with fill color using the borb library in Python


I am currently working on creating PDFs using the borb library in Python. I have successfully created a rectangle object using borb and filled it with a desired colour. However, when I try to place text on top of this rectangle object, the text seems to be hidden behind the bounding box of the rectangle, and I am unable to view it.

import typing
from decimal import Decimal

from borb.pdf import Document
from borb.pdf import PDF
from borb.pdf import Page
from borb.pdf import Paragraph
from borb.pdf import HexColor
from borb.pdf.canvas.geometry.rectangle import Rectangle
from borb.pdf.canvas.layout.annotation.square_annotation import SquareAnnotation


def main():
    # CREATE A DOCUMENT #######################################################
    doc: Document = Document()

    # CREATE A PAGE ###########################################################
    page: Page = Page()

    # ADD A PAGE TO THE DOCUMENT ##############################################
    doc.add_page(page)

    # GET PAGE WIDTH AND HEIGHT ###############################################
    PAGE_WIDTH: typing.Optional[Decimal] = page.get_page_info().get_width()
    assert PAGE_WIDTH is not None

    PAGE_HEIGHT: typing.Optional[Decimal] = page.get_page_info().get_height()
    assert PAGE_WIDTH is not None

    # SET HEADER BOUNDING BOX #################################################

    HEADER_HEIGHT: int = 70
    header_bb: Rectangle = Rectangle(
        Decimal(0),
        Decimal(PAGE_HEIGHT - HEADER_HEIGHT),
        Decimal(PAGE_WIDTH),
        Decimal(HEADER_HEIGHT),
    )

    page.add_annotation(SquareAnnotation(
        bounding_box = header_bb,
        stroke_color = HexColor("#2f5496"),
        fill_color   = HexColor("#2f5496")    # LINE 43
    ))

    # ADD A TEXT OVER BOUNDING BOX ############################################

    Paragraph("Sample Text").paint(page, header_bb)

    with open("borb-pdf.pdf", "wb") as out_file_handle:
        PDF.dumps(out_file_handle, doc)


if __name__ == "__main__":
    main()

In this code, the rectangle is displayed with the specified fill colour, but the text "Sample Text" does not appear on top of the rectangle. However, if I comment on line 43 then I can view the PDF.

I suspect that the text is being placed behind the bounding box of the rectangle, causing it to be hidden. How can I ensure that the text is displayed on top of the rectangle with the fill colour applied?

enter image description here

Any insights or suggestions would be greatly appreciated.


Solution

  • disclaimer: I am the author of the borb library

    Annotations are always displayed on top. Think of them as "something that can be done to an existing document" and hopefully the analogy makes sense.

    You can use ConnectedShape to draw a Rectangle and fill it. This approach will have the desired effect (meaning the content is rendered in the order you added it to the Page)

    Adding a ConnectedShape at a precise location can be done using the following code:

    from borb.pdf import (
        Page,
        Document,
        SingleColumnLayout,
        Paragraph,
        PDF,
        ConnectedShape,
        LineArtFactory,
        HexColor,
    )
    from borb.pdf.canvas.geometry.rectangle import Rectangle
    
    
    def main():
    
        d = Document()
    
        p = Page()
        d.add_page(p)
    
        l = SingleColumnLayout(p)
        l.add(
            Paragraph(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
                "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco "
                "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
            )
        )
    
        # define Rectangle
        r: Rectangle = Rectangle(100, 100, 64, 64)
    
        # paint ConnectedShape
        ConnectedShape(
            LineArtFactory.rectangle(r),
            stroke_color=HexColor("ff0000"),
            fill_color=HexColor("00ff00"),
        ).paint(page=p, available_space=r)
    
        # store PDF
        with open("output.pdf", "wb") as fh:
            PDF.dumps(fh, d)
    
    
    if __name__ == "__main__":
        main()
    
    

    Which yields the following PDF: enter image description here