1 |
0ea528a4
|
Mikaël Ates
|
# -*- coding: utf-8 -*-
|
2 |
|
|
|
3 |
|
|
import os
|
4 |
|
|
import tempfile
|
5 |
|
|
|
6 |
|
|
import cairo
|
7 |
|
|
import pango
|
8 |
|
|
import pangocairo
|
9 |
|
|
|
10 |
|
|
from ..pdftk import PdfTk
|
11 |
|
|
|
12 |
|
|
|
13 |
|
|
class TransportTemplate(object):
|
14 |
|
|
fields = {
|
15 |
|
|
'NOM_BENEFICIAIRE': {
|
16 |
9b58dc83
|
Jérôme Schneider
|
'pos': (302, 172),
|
17 |
0ea528a4
|
Mikaël Ates
|
},
|
18 |
|
|
'PRENOM_BENEFICIAIRE': {
|
19 |
9b58dc83
|
Jérôme Schneider
|
'pos': (136, 186),
|
20 |
0ea528a4
|
Mikaël Ates
|
},
|
21 |
|
|
'DATE': {
|
22 |
9b58dc83
|
Jérôme Schneider
|
'pos': (530, 582),
|
23 |
|
|
'size': 7,
|
24 |
0ea528a4
|
Mikaël Ates
|
},
|
25 |
|
|
'LIEU': {
|
26 |
9b58dc83
|
Jérôme Schneider
|
'pos': (591, 583),
|
27 |
|
|
'size': 7,
|
28 |
0ea528a4
|
Mikaël Ates
|
},
|
29 |
|
|
'IDENTIFICATION_ETABLISSEMENT': {
|
30 |
|
|
'type': 'multiline',
|
31 |
9b58dc83
|
Jérôme Schneider
|
'pos': (510, 638),
|
32 |
0ea528a4
|
Mikaël Ates
|
},
|
33 |
|
|
'NIR_ASSURE': {
|
34 |
9b58dc83
|
Jérôme Schneider
|
'pos': (325, 781),
|
35 |
0ea528a4
|
Mikaël Ates
|
'size': 10,
|
36 |
|
|
},
|
37 |
|
|
'NIR_KEY_ASSURE': {
|
38 |
9b58dc83
|
Jérôme Schneider
|
'pos': (527, 781),
|
39 |
0ea528a4
|
Mikaël Ates
|
'size': 10,
|
40 |
|
|
},
|
41 |
|
|
'NOM_ASSURE': {
|
42 |
9b58dc83
|
Jérôme Schneider
|
'pos': (492, 805),
|
43 |
0ea528a4
|
Mikaël Ates
|
},
|
44 |
|
|
'CODE_ORGANISME_1': {
|
45 |
9b58dc83
|
Jérôme Schneider
|
'pos': (328, 832),
|
46 |
0ea528a4
|
Mikaël Ates
|
'size': 10,
|
47 |
|
|
},
|
48 |
|
|
'CODE_ORGANISME_2': {
|
49 |
9b58dc83
|
Jérôme Schneider
|
'pos': (357, 832),
|
50 |
0ea528a4
|
Mikaël Ates
|
'size': 10,
|
51 |
|
|
},
|
52 |
|
|
'CODE_ORGANISME_3': {
|
53 |
9b58dc83
|
Jérôme Schneider
|
'pos': (401, 832),
|
54 |
0ea528a4
|
Mikaël Ates
|
'size': 10,
|
55 |
|
|
},
|
56 |
|
|
'ADRESSE_BENEFICIAIRE': {
|
57 |
9b58dc83
|
Jérôme Schneider
|
'pos': (94, 873),
|
58 |
0ea528a4
|
Mikaël Ates
|
},
|
59 |
c8954c82
|
Mikaël Ates
|
'SITUATION_CHOICE_1': {
|
60 |
9b58dc83
|
Jérôme Schneider
|
'pos': (386, 241),
|
61 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
62 |
|
|
},
|
63 |
|
|
'SITUATION_CHOICE_2': {
|
64 |
9b58dc83
|
Jérôme Schneider
|
'pos': (386, 262),
|
65 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
66 |
|
|
},
|
67 |
|
|
'SITUATION_CHOICE_3': {
|
68 |
9b58dc83
|
Jérôme Schneider
|
'pos': (711, 240),
|
69 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
70 |
|
|
},
|
71 |
|
|
'SITUATION_CHOICE_4': {
|
72 |
9b58dc83
|
Jérôme Schneider
|
'pos': (711, 259),
|
73 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
74 |
|
|
},
|
75 |
|
|
'SITUATION_DATE': {
|
76 |
9b58dc83
|
Jérôme Schneider
|
'pos': (606, 280),
|
77 |
c8954c82
|
Mikaël Ates
|
'size': 8,
|
78 |
|
|
},
|
79 |
|
|
'TRAJET_TEXT': {
|
80 |
9b58dc83
|
Jérôme Schneider
|
'pos': (84, 320),
|
81 |
c8954c82
|
Mikaël Ates
|
'size': 8,
|
82 |
|
|
},
|
83 |
|
|
'TRAJET_CHOICE_1': {
|
84 |
9b58dc83
|
Jérôme Schneider
|
'pos': (193, 375),
|
85 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
86 |
|
|
},
|
87 |
|
|
'TRAJET_CHOICE_2': {
|
88 |
9b58dc83
|
Jérôme Schneider
|
'pos': (441, 375),
|
89 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
90 |
|
|
},
|
91 |
|
|
'TRAJET_CHOICE_3': {
|
92 |
9b58dc83
|
Jérôme Schneider
|
'pos': (711, 376),
|
93 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
94 |
|
|
},
|
95 |
|
|
'TRAJET_NUMBER': {
|
96 |
9b58dc83
|
Jérôme Schneider
|
'pos': (308, 383),
|
97 |
c8954c82
|
Mikaël Ates
|
'size': 8,
|
98 |
|
|
},
|
99 |
|
|
'PC_CHOICE_1': {
|
100 |
9b58dc83
|
Jérôme Schneider
|
'pos': (564, 410),
|
101 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
102 |
|
|
},
|
103 |
|
|
'PC_CHOICE_2': {
|
104 |
9b58dc83
|
Jérôme Schneider
|
'pos': (638, 410),
|
105 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
106 |
|
|
},
|
107 |
|
|
'MODE_CHOICE_1': {
|
108 |
9b58dc83
|
Jérôme Schneider
|
'pos': (320, 473),
|
109 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
110 |
|
|
},
|
111 |
|
|
'MODE_CHOICE_2': {
|
112 |
9b58dc83
|
Jérôme Schneider
|
'pos': (320, 488),
|
113 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
114 |
|
|
},
|
115 |
|
|
'MODE_CHOICE_3': {
|
116 |
9b58dc83
|
Jérôme Schneider
|
'pos': (320, 504),
|
117 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
118 |
|
|
},
|
119 |
|
|
'MODE_CHOICE_4': {
|
120 |
9b58dc83
|
Jérôme Schneider
|
'pos': (564, 517),
|
121 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
122 |
|
|
},
|
123 |
|
|
'MODE_CHOICE_5': {
|
124 |
9b58dc83
|
Jérôme Schneider
|
'pos': (638, 517),
|
125 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
126 |
|
|
},
|
127 |
|
|
'MODE_CHOICE_6': {
|
128 |
9b58dc83
|
Jérôme Schneider
|
'pos': (320, 536),
|
129 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
130 |
|
|
},
|
131 |
|
|
'CDTS_CHOICE_1': {
|
132 |
9b58dc83
|
Jérôme Schneider
|
'pos': (400, 552),
|
133 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
134 |
|
|
},
|
135 |
|
|
'CDTS_CHOICE_2': {
|
136 |
9b58dc83
|
Jérôme Schneider
|
'pos': (661, 552),
|
137 |
c8954c82
|
Mikaël Ates
|
'type': 'bool',
|
138 |
|
|
},
|
139 |
0ea528a4
|
Mikaël Ates
|
}
|
140 |
|
|
|
141 |
|
|
def __init__(self, template_path=None, prefix='tmp', suffix=''):
|
142 |
|
|
self.prefix = prefix
|
143 |
|
|
self.suffix = suffix
|
144 |
|
|
self.template_path = template_path
|
145 |
|
|
|
146 |
|
|
def draw_field(self, ctx, field, value, size=9):
|
147 |
|
|
_type = field.get('type', 'text')
|
148 |
|
|
size = field.get('size', size)
|
149 |
|
|
if _type == 'bool':
|
150 |
|
|
x, y = field['pos']
|
151 |
|
|
if value:
|
152 |
|
|
ctx.move_to(x, y - 10)
|
153 |
|
|
pangocairo_context = pangocairo.CairoContext(ctx)
|
154 |
|
|
pangocairo_context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
|
155 |
|
|
|
156 |
|
|
layout = pangocairo_context.create_layout()
|
157 |
|
|
font = pango.FontDescription("Georgia %s" % size)
|
158 |
|
|
layout.set_font_description(font)
|
159 |
|
|
|
160 |
|
|
layout.set_text(u'\u2714')
|
161 |
|
|
pangocairo_context.update_layout(layout)
|
162 |
|
|
pangocairo_context.show_layout(layout)
|
163 |
|
|
if _type in ('text', 'multiline'):
|
164 |
|
|
x, y = field['pos']
|
165 |
|
|
ctx.move_to(x, y)
|
166 |
|
|
pangocairo_context = pangocairo.CairoContext(ctx)
|
167 |
|
|
pangocairo_context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
|
168 |
|
|
|
169 |
|
|
layout = pangocairo_context.create_layout()
|
170 |
|
|
font = pango.FontDescription("Georgia Bold %s" % size)
|
171 |
|
|
layout.set_font_description(font)
|
172 |
|
|
|
173 |
|
|
layout.set_text(unicode(value))
|
174 |
|
|
pangocairo_context.update_layout(layout)
|
175 |
|
|
if field.get('border'):
|
176 |
|
|
a, b, width, height = layout.get_pixel_extents()[1]
|
177 |
|
|
ctx.save()
|
178 |
|
|
ctx.set_source_rgb(1, 1, 1)
|
179 |
|
|
ctx.rectangle(x - 2, y - 2, width + 4, height + 4)
|
180 |
|
|
ctx.fill()
|
181 |
|
|
ctx.set_source_rgb(0, 0, 0)
|
182 |
|
|
ctx.rectangle(x - 2, y - 2, width + 4, height + 4)
|
183 |
|
|
ctx.set_line_width(0.1)
|
184 |
|
|
ctx.stroke()
|
185 |
|
|
ctx.restore()
|
186 |
|
|
ctx.move_to(x, y)
|
187 |
|
|
pangocairo_context.show_layout(layout)
|
188 |
|
|
if _type == 'array':
|
189 |
|
|
field = field.copy()
|
190 |
|
|
y = field['y']
|
191 |
|
|
offset = field.get('x', 0)
|
192 |
|
|
for row in value:
|
193 |
|
|
for x, v in zip(field['cols'], row):
|
194 |
|
|
sub = {
|
195 |
|
|
'size': size,
|
196 |
|
|
}
|
197 |
|
|
self.draw_field(ctx, sub, v, 7)
|
198 |
|
|
y += field['lineheight']
|
199 |
|
|
|
200 |
9b58dc83
|
Jérôme Schneider
|
def draw_grid(self, ctx):
|
201 |
|
|
ctx.set_source_rgb(0, 0, 0)
|
202 |
|
|
for i in range(0, 827, 100):
|
203 |
|
|
ctx.move_to(i, 5)
|
204 |
|
|
ctx.show_text(str(i // 100));
|
205 |
|
|
ctx.move_to(i, 0)
|
206 |
|
|
ctx.line_to(i, 1169)
|
207 |
|
|
ctx.stroke()
|
208 |
|
|
for i in range(0, 1169, 100):
|
209 |
|
|
ctx.move_to(0, i-5)
|
210 |
|
|
ctx.show_text(str(i // 100))
|
211 |
|
|
ctx.move_to(0, i)
|
212 |
|
|
ctx.line_to(827, i)
|
213 |
|
|
ctx.stroke()
|
214 |
|
|
|
215 |
0ea528a4
|
Mikaël Ates
|
def generate(self, content, delete=True):
|
216 |
|
|
width, height = 827, 1169
|
217 |
|
|
with tempfile.NamedTemporaryFile(prefix=self.prefix,
|
218 |
|
|
suffix=self.suffix, delete=False) as temp_out_pdf:
|
219 |
|
|
try:
|
220 |
|
|
overlay = tempfile.NamedTemporaryFile(prefix='overlay',
|
221 |
|
|
suffix='.pdf')
|
222 |
|
|
surface = cairo.PDFSurface(overlay.name, width, height)
|
223 |
|
|
ctx = cairo.Context(surface)
|
224 |
|
|
ctx.set_source_rgb(0, 0, 0)
|
225 |
|
|
for key, value in content.iteritems():
|
226 |
|
|
field = self.fields[key]
|
227 |
|
|
self.draw_field(ctx, field, value)
|
228 |
|
|
ctx.show_page()
|
229 |
|
|
surface.finish()
|
230 |
|
|
pdftk = PdfTk()
|
231 |
|
|
pdftk.background(overlay.name, self.template_path,
|
232 |
|
|
temp_out_pdf.name)
|
233 |
|
|
overlay.close()
|
234 |
|
|
return temp_out_pdf.name
|
235 |
|
|
except:
|
236 |
|
|
if delete:
|
237 |
|
|
try:
|
238 |
|
|
os.unlink(temp_out_pdf.name)
|
239 |
|
|
except:
|
240 |
|
|
pass
|
241 |
|
|
raise
|