source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/contrib/fpdf/template.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 9.2 KB
Line 
1# -*- coding: iso-8859-1 -*-
2
3"PDF Template Helper for FPDF.py"
4
5from __future__ import with_statement
6
7__author__ = "Mariano Reingart <reingart@gmail.com>"
8__copyright__ = "Copyright (C) 2010 Mariano Reingart"
9__license__ = "LGPL 3.0"
10
11import sys,os,csv
12from .fpdf import FPDF
13from .py3k import PY3K, basestring, unicode
14
15def rgb(col):
16    return (col // 65536), (col // 256 % 256), (col% 256)
17
18class Template:
19    def __init__(self, infile=None, elements=None, format='A4', orientation='portrait',
20                 title='', author='', subject='', creator='', keywords=''):
21        if elements:
22            self.load_elements(elements)
23        self.handlers = {'T': self.text, 'L': self.line, 'I': self.image,
24                         'B': self.rect, 'BC': self.barcode, 'W': self.write, }
25        self.texts = {}
26        pdf = self.pdf = FPDF(format=format,orientation=orientation, unit="mm")
27        pdf.set_title(title)
28        pdf.set_author(author)
29        pdf.set_creator(creator)
30        pdf.set_subject(subject)
31        pdf.set_keywords(keywords)
32
33    def load_elements(self, elements):
34        "Initialize the internal element structures"
35        self.pg_no = 0
36        self.elements = elements
37        self.keys = [v['name'].lower() for v in self.elements]
38   
39    def parse_csv(self, infile, delimiter=",", decimal_sep="."):
40        "Parse template format csv file and create elements dict"
41        keys = ('name','type','x1','y1','x2','y2','font','size',
42            'bold','italic','underline','foreground','background',
43            'align','text','priority', 'multiline')
44        self.elements = []
45        self.pg_no = 0
46        if not PY3K:
47            f = open(infile, 'rb')
48        else:
49            f = open(infile)
50        with f:
51            for row in csv.reader(f, delimiter=delimiter):
52                kargs = {}
53                for i,v in enumerate(row):
54                    if not v.startswith("'") and decimal_sep!=".":
55                        v = v.replace(decimal_sep,".")
56                    else:
57                        v = v
58                    if v=='':
59                        v = None
60                    else:
61                        v = eval(v.strip())
62                    kargs[keys[i]] = v
63                self.elements.append(kargs)
64        self.keys = [v['name'].lower() for v in self.elements]
65
66    def add_page(self):
67        self.pg_no += 1
68        self.texts[self.pg_no] = {}
69       
70    def __setitem__(self, name, value):
71        if name.lower() in self.keys:
72            if not PY3K and isinstance(value, unicode):
73                value = value.encode("latin1","ignore")
74            elif value is None:
75                value = ""
76            else:
77                value = str(value)
78            self.texts[self.pg_no][name.lower()] = value
79
80    # setitem shortcut (may be further extended)
81    set = __setitem__
82
83    def has_key(self, name):
84        return name.lower() in self.keys
85       
86    def __getitem__(self, name):
87        if name in self.keys:
88            key = name.lower()
89            if key in self.texts:
90                # text for this page:
91                return self.texts[self.pg_no][key]
92            else:
93                # find first element for default text:
94                elements = [element for element in self.elements
95                    if element['name'].lower() == key]
96                if elements:
97                    return elements[0]['text']
98
99    def split_multicell(self, text, element_name):
100        "Divide (\n) a string using a given element width"
101        pdf = self.pdf
102        element = [element for element in self.elements
103            if element['name'].lower() == element_name.lower()][0]
104        style = ""
105        if element['bold']: style += "B"
106        if element['italic']: style += "I"
107        if element['underline']: style += "U"
108        pdf.set_font(element['font'],style,element['size'])
109        align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(element['align']) # D/I in spanish
110        if isinstance(text, unicode) and not PY3K:
111            text = text.encode("latin1","ignore")
112        else:
113            text = str(text)
114        return pdf.multi_cell(w=element['x2']-element['x1'],
115                             h=element['y2']-element['y1'],
116                             txt=text,align=align,split_only=True)
117       
118    def render(self, outfile, dest="F"):
119        pdf = self.pdf
120        for pg in range(1, self.pg_no+1):
121            pdf.add_page()
122            pdf.set_font('Arial','B',16)
123            pdf.set_auto_page_break(False,margin=0)
124
125            for element in sorted(self.elements,key=lambda x: x['priority']):
126                #print "dib",element['type'], element['name'], element['x1'], element['y1'], element['x2'], element['y2']
127                element = element.copy()
128                element['text'] = self.texts[pg].get(element['name'].lower(), element['text'])
129                if 'rotate' in element:
130                    pdf.rotate(element['rotate'], element['x1'], element['y1'])
131                self.handlers[element['type'].upper()](pdf, **element)
132                if 'rotate' in element:
133                    pdf.rotate(0)
134       
135        if dest:
136            return pdf.output(outfile, dest)
137       
138    def text(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=10,
139             bold=False, italic=False, underline=False, align="",
140             foreground=0, backgroud=65535, multiline=None,
141             *args, **kwargs):
142        if text:
143            if pdf.text_color!=rgb(foreground):
144                pdf.set_text_color(*rgb(foreground))
145            if pdf.fill_color!=rgb(backgroud):
146                pdf.set_fill_color(*rgb(backgroud))
147
148            font = font.strip().lower()
149            if font == 'arial black':
150                font = 'arial'
151            style = ""
152            for tag in 'B', 'I', 'U':
153                if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
154                    text = text[3:-4]
155                    style += tag
156            if bold: style += "B"
157            if italic: style += "I"
158            if underline: style += "U"
159            align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
160            pdf.set_font(font,style,size)
161            ##m_k = 72 / 2.54
162            ##h = (size/m_k)
163            pdf.set_xy(x1,y1)
164            if multiline is None:
165                # multiline==None: write without wrapping/trimming (default)
166                pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align)
167            elif multiline:
168                # multiline==True: automatic word - warp
169                pdf.multi_cell(w=x2-x1,h=y2-y1,txt=text,border=0,align=align)
170            else:
171                # multiline==False: trim to fit exactly the space defined
172                text = pdf.multi_cell(w=x2-x1, h=y2-y1,
173                             txt=text, align=align, split_only=True)[0]
174                print("trimming: *%s*" % text)
175                pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align)
176
177            #pdf.Text(x=x1,y=y1,txt=text)
178
179    def line(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, foreground=0, *args, **kwargs):
180        if pdf.draw_color!=rgb(foreground):
181            #print "SetDrawColor", hex(foreground)
182            pdf.set_draw_color(*rgb(foreground))
183        #print "SetLineWidth", size
184        pdf.set_line_width(size)
185        pdf.line(x1, y1, x2, y2)
186
187    def rect(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, foreground=0, backgroud=65535, *args, **kwargs):
188        if pdf.draw_color!=rgb(foreground):
189            pdf.set_draw_color(*rgb(foreground))
190        if pdf.fill_color!=rgb(backgroud):
191            pdf.set_fill_color(*rgb(backgroud))
192        pdf.set_line_width(size)
193        pdf.rect(x1, y1, x2-x1, y2-y1)
194
195    def image(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', *args,**kwargs):
196        if text:
197            pdf.image(text,x1,y1,w=x2-x1,h=y2-y1,type='',link='')
198
199    def barcode(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
200             foreground=0, *args, **kwargs):
201        if pdf.draw_color!=rgb(foreground):
202            pdf.set_draw_color(*rgb(foreground))
203        font = font.lower().strip()
204        if font == 'interleaved 2of5 nt':
205            pdf.interleaved2of5(text,x1,y1,w=size,h=y2-y1)
206
207    # Added by Derek Schwalenberg Schwalenberg1013@gmail.com to allow (url) links in templates (using write method) 2014-02-22
208    def write(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1,
209              bold=False, italic=False, underline=False, align="", link='http://example.com',
210             foreground=0, *args, **kwargs):
211        if pdf.text_color!=rgb(foreground):
212            pdf.set_text_color(*rgb(foreground))
213        font = font.strip().lower()
214        if font == 'arial black':
215            font = 'arial'
216        style = ""
217        for tag in 'B', 'I', 'U':
218            if (text.startswith("<%s>" % tag) and text.endswith("</%s>" %tag)):
219                text = text[3:-4]
220                style += tag
221        if bold: style += "B"
222        if italic: style += "I"
223        if underline: style += "U"
224        align = {'L':'L','R':'R','I':'L','D':'R','C':'C','':''}.get(align) # D/I in spanish
225        pdf.set_font(font,style,size)
226        ##m_k = 72 / 2.54
227        ##h = (size/m_k)
228        pdf.set_xy(x1,y1)
229        pdf.write(5,text,link)
Note: See TracBrowser for help on using the repository browser.