How to add bold and normal text in one line using drawString method in reportlab (python)

Omkar picture Omkar · Jan 1, 2015 · Viewed 22.2k times · Source

I am new to reportlab lib, I am learning it simultaneously working on a college project. I have created a desktop application in wxpython, which result in saving data in PDF.

I want to add 2 lines in my pdf. Where line starts with a user input called name, then some words, again at 2nd line some words, user name and then again some words...

I tried use some of Paragraph and canvas methods and classes but I wasn't able to get the desired output.

Desired output:

Alex is working on college project.

reportlab is very good lib, Alex liked it.

My code:

import os
import reportlab
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.pdfmetrics import registerFontFamily
from reportlab.pdfbase.ttfonts import TTFont

# Registered font family
pdfmetrics.registerFont(TTFont('Vera', 'Vera.ttf'))
pdfmetrics.registerFont(TTFont('VeraBd', 'VeraBd.ttf'))
pdfmetrics.registerFont(TTFont('VeraIt', 'VeraIt.ttf'))
pdfmetrics.registerFont(TTFont('VeraBI', 'VeraBI.ttf'))
# Registered fontfamily
registerFontFamily('Vera',normal='Vera',bold='VeraBd',italic='VeraIt',boldItalic='VeraBI')

# Output pdf file name.
can = canvas.Canvas("Bold_Trail.pdf", pagesize=A4)

# Setfont for whole pdf.
can.setFont('Vera', 12)

# student name variable.
student_name ="Alex"

# Content.
line1 = " is working on college project."
line2 = "Reportlab is very good lib, "
line3 = " liked it.<br>"

# Joining whole content together.
content = "<strong>" + student_name + "</strong>" + line1
content2 = line2 + "<strong>"+student_name + "</strong>" + line3

# drawString location calculation.
x = 0; y = 8.5 * 72

# First string.
can.drawString(x,y, content)

y = y - 72

# Second String.
can.drawString(x,y, content2)

# Create PDF.
can.save()

Is there any other way except using XML method <strong> or <b> that do not work in the above program?

The words should remain on one line.

Answer

jbihan picture jbihan · Jan 1, 2015

You could use the setFont method of the canvas object, to set the font to Bold when needed, and Normal otherwise.

* UPDATE *

In order to calculate the right value for x, you can use the stringWidth method, that calculates the length of the string given its content, the font name and the font size. You will have to import it from reportlab.pdfbase.pdfmetrics:

[...]
from reportlab.pdfbase.pdfmetrics import stringWidth
[...]

# student name variable.
student_name = 'Alex'

# Content.
line1 = " is working on college project."
line2 = "Reportlab is very good lib, "
line3 = " liked it"

# drawString location calculation.
x = 0
y = 8.5 * 72

# First string.
can.setFont('Helvetica-Bold', 8)
can.drawString(x, y, student_name)
can.setFont('Helvetica', 8)
textWidth = stringWidth(student_name, 'Helvetica-Bold', 8) 
x += textWidth + 1
can.drawString(x, y, line1)

y = y - 72

# Second String.
x = 0
can.setFont('Helvetica', 8)
can.drawString(x, y, line2)
textWidth = stringWidth(line2, 'Helvetica', 8) 
x += textWidth + 1
can.setFont('Helvetica-Bold', 8)
can.drawString(x, y, student_name)
textWidth = stringWidth(student_name, 'Helvetica-Bold', 8) 
x += textWidth + 1
can.setFont('Helvetica', 8)
can.drawString(x, y, line3)

# Create PDF.
can.save()

Or you could have a look at ParagraphStyle and Paragraph (from reportlab.lib.styles import ParagraphStyle, from reportlab.platypus import Paragraph) but I am not sure if you can concatenate two different styles in the same string.