Search code examples
pythonpdfreportlab

Align watermark horizontally in the middle in PDF?


i try to align a watermark in a pdf so it is exactly in the middle at the bottom with the following code:

from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase.pdfmetrics import stringWidth

# text = "test test test"
text = "Peter Schmidt, Musterstraße 1, 50767 Köln"
pdf = canvas.Canvas("watermark.pdf", pagesize=A4)
pdf.translate(inch, inch)
pdf.setFillColor(colors.grey, alpha=0.6)
pdf.setFont("Helvetica", 15)
widthText = stringWidth(text, "Helvetica", 15) / 2
widthPage = pdf._pagesize[0]
x = (widthPage / 2) - (widthText / 2)
pdf.drawCentredString(x, -45, text)
pdf.save()

Generally it seems to work fine and when i use the text

text = "Peter Schmidt, Musterstraße 1, 50767 Köln"

it centers fine

enter image description here

but when i try it with a shorter text like

text = "test test test"

its not working anymore and the text is far to right

enter image description here

How can i solve this that the text is allways in the middle of the pdf?


Solution

  • The issue here is that the horizontal Zero Position is not at the very left of the page but shifted right for some amount that serves as the left margin of the page. You need to find out, how big that margin is in order to calculate the correct position. If you are using a document template, that margin is defined somewhere in that template. I have not jet found a way to get the margin size programmatically without a template. But Using your code on my system appears to result in a left margin of 70.

    With that information, the following code yields the desired result:

    from reportlab.pdfgen import canvas
    from reportlab.lib.units import inch
    from reportlab.lib import colors
    from reportlab.lib.pagesizes import A4
    from reportlab.pdfbase.pdfmetrics import stringWidth
    
    text = "test test test"
    #text = "Peter Schmidt, Musterstraße 1, 50767 Köln"
    #text = "1"
    pdf = canvas.Canvas("watermark.pdf", pagesize=A4)
    pdf.translate(inch, inch)
    pdf.setFillColor(colors.grey, alpha=0.6)
    pdf.setFont("Helvetica", 15)
    widthPage = pdf._pagesize[0]
    leftMargin = 70     # acquired experimentally
    
    # option 1 using drawCentredString()
    x = (widthPage / 2) - leftMargin
    pdf.drawCentredString(x, 0, text)
    
    # option 2 using drawString()
    widthText = stringWidth(text, "Helvetica", 15)
    x2 = (widthPage / 2) - (widthText / 2) - leftMargin
    pdf.drawString(x2, -45, text)
    
    pdf.save()
    

    The fact that you code worked for the long string was pure luck. Note that the option using the drawCentredString() method does not need the width of the test at all.

    The option using the drawString() method does need the width of the string. Note that the /2 is removed from the calculation of widthText to yield the correct width.