1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
# -*- coding: utf-8 -*-
# __author__ = jeff@openerp.cn,joshua@openerp.cn
##############################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
from reportlab.lib.fontfinder import FontFinder
from reportlab import rl_config
import os
import re
RMLS = ['rml_header','rml_header2','rml_header3']
class oecn_base_fonts_map(osv.osv_memory):
_name = 'oecn_base_fonts.map'
# try to get the font from the cache first (system_fonts)
system_fonts = []
def __system_fonts_get(self, cr, uid, context=None):
if self.system_fonts:
return self.system_fonts
else:
return self._system_fonts_get(cr, uid)
def _system_fonts_get(self, cr, uid, context = None):
''' get fonts list on server '''
# consider both windows and unix like systems
res = []
env = {
'windir': os.environ.get('windir', os.getcwd()),
'home': os.environ.get('HOME', os.getcwd()),
}
FontFolders = [
'%(windir)s/Fonts',
'/usr/share/fonts',
'%(home)s/tmp/corefonts',
]
folders = [ s % env for s in FontFolders]
# get all folders under fonts directory
ff = FontFinder( useCache = False )
fontdirs = folders[:]
for ele in folders:
for root, dirs, files in os.walk(ele):
for name in dirs:
fontdirs.append(os.path.join(root, name))
ff.addDirectories(set(fontdirs))
# get fonts name and file path
# ff.search() may resulting error if any AFMFont resided in
# the search path has defined width that is not an integer
# a dirty workaround:
# replace following code around #110 in reportlab.pdfbase.pdfmetrics
# From:
# width = string.atoi(r)
# To:
# width = int(float(r))
ff.search()
for familyName in ff.getFamilyNames():
for font in ff.getFontsInFamily(familyName):
if font.fileName[-4:].lower() in (".ttf", ".ttc"):
res.append((font.fileName, font.name))
#cache the font list in class variable
oecn_base_fonts_map.system_fonts = res
return res
def _pdf_fonts_get(self, cr, uid, context = None):
return [('Helvetica','Helvetica'), \
('DejaVuSans','DejaVuSans'), \
('Times','Times'), \
('Times-Roman','Times-Roman'), \
('Courier', 'Courier')]
_columns = {
'map_id':fields.many2one('oecn_base_fonts.config','Font Map', required=True),
'pdf_font':fields.selection(_pdf_fonts_get, 'Original Fonts', required=True),
'name':fields.char('Font Alias', size=20, required=True, help='use this font alias \
in custom rml report template'),
'new_font':fields.selection(__system_fonts_get, 'Replaced With', required=True),
}
def onchange_new_font(self, cr, uid, ids, new_font):
"""get the default 'Font Alias'"""
for font_path, font_name in self.system_fonts:
if new_font == font_path:
return {'value': {'name': font_name}}
oecn_base_fonts_map()
class oecn_base_fonts_config(osv.osv_memory):
_name = 'oecn_base_fonts.config'
_inherit = 'res.config'
_columns = {
'wrap':fields.boolean('CJK wrap', required=True, \
help="If you are using CJK fonts, check this option will wrap your \
words properly at the edge of the pdf report"),
'map_ids':fields.one2many('oecn_base_fonts.map','map_id','Replace Fonts'),
}
_defaults = {
'wrap': True
}
def execute(self, cr, uid, ids, context=None):
company_obj = self.pool.get('res.company')
company_ids = company_obj.search(cr, uid, [])
p = re.compile('<setFont.*(?=size.*)')
#Replace the font in company rml headrer and footer
for o in self.browse(cr, uid, ids, context=context):
config_obj = self.pool.get('ir.config_parameter')
maps = []
for map in o.map_ids:
maps = maps + [(map.pdf_font, map.name ,map.new_font,'all')]
config_obj.set_param(cr, uid, 'fonts_map', {'wrap':o.wrap,'maps':maps})
for company in company_obj.read(cr, uid, company_ids, RMLS):
value = {}
for rml in RMLS:
new_font_rml = '<setFont name="'+o.map_ids[0].name+'" '
value[rml] = p.sub(new_font_rml, company[rml])
company_obj.write(cr, uid, company['id'], value)
oecn_base_fonts_config()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|