Print a text at a specific location on the page

Peter Otten __peter__ at web.de
Wed Dec 4 11:57:08 CET 2013


loic.espern at gmail.com wrote:

> Hi all
> 
> This is my first post on this list :-)
> 
> I have a web-application (developped using a python framework). In this
> web-app, I would like to print certificates for some courses.
> 
> The principle :
> The course teacher has a "default" certificates, with placeholders for the
> name, and the certification name. ("Congratulations _______ you
> successfully passed the ______ course") He puts the certificate in his
> printer, and my app prints the name, and the certification on a specific
> location, to fill the placeholders.
> 
> I looked at ReportLab, and Pod. They seems powerfull to build complex
> reports, but I wonder if it exists a simpler solution just to print a text
> at a specific place on the page...
> 
> Thank you

I have the following quick-and-dirty wrapper for cairographics lying around 
-- just added the demo.

#/usr/bin/env python3
import cairo
import math

from contextlib import contextmanager

A4 = 595, 842

_mm = 72/25.4

def mm(x):
    """Convert mm to cairo-native (point)"""
    return x * _mm

class Context(object):
    """Wrapper for a cairo context object.

    Methods it doesn't provide are delegated to the cairo.Context instance.
    """
    def __init__(self, width, height, context):
        self.width = width
        self.height = height
        self.context = context
    def __getattr__(self, name):
        """Unknown attribute, delegate to cairo context
        """
        return getattr(self.context, name)
    @contextmanager
    def fontsize(self, size):
        """Set fontsize temporarily to something other than 12pt"""
        self.context.set_font_size(size)
        yield
        self.context.set_font_size(12)
    def line(self, start_x, start_y, end_x, end_y):
        """Draw a line from (start_x, start_y) to (end_x, end_y)"""
        self.context.move_to(start_x, start_y)
        self.context.line_to(end_x, end_y)
    def text_at(self, left, top, text):
        """Draw `text` at position (left, top)"""
        self.context.move_to(left, top)
        self.context.text_path(text)

def setup_context(
    filename, size, landscape,
    font="Times New Roman",
    slant=cairo.FONT_SLANT_NORMAL):
    """Create a cairo drawing context suitable for
    printing in landscape format.
    """
    width, height = size

    # http://cairographics.org/documentation/using_the_postscript_surface/
    # recommends the following for printing in landscape
    #
    # the "natural" approach (swapping width and height directly without
    # dsc_comment, translate, rotate, looked OK in Okular resulted in 
misplaced
    # (large left/top offset, bottom right corner clipped) output in print
    surface = cairo.PSSurface(filename, width, height)
    if landscape:
        surface.dsc_comment("%%PageOrientation: Landscape")
        context = cairo.Context(surface)
        context.translate(0, height)
        context.rotate(-math.pi/2)
        width, height = height, width
    else:
        context = cairo.Context(surface)

    context.select_font_face(
        font, slant, cairo.FONT_WEIGHT_NORMAL)
    context.set_font_size(12)
    context.set_line_width(.5)

    return Context(width, height, context)

if __name__ == "__main__":
    def demo():
        context = setup_context("tmp.ps", A4, landscape=False, font="Times")
        with context.fontsize(18):
            context.text_at(mm(20), mm(100), "Max Mustermann")
            context.text_at(mm(120), mm(100), "Brewing")
        context.fill()
    demo()

If that's too dirty for you consider using cairographics directly...




More information about the Python-list mailing list