diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index 03fcb133d9f..d61963dbce4 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -20,14 +20,15 @@ ############################################################################## import os - +import re import openerp from openerp import SUPERUSER_ID, tools from openerp.osv import fields, osv from openerp.tools.translate import _ from openerp.tools.safe_eval import safe_eval as eval from openerp.tools import image_resize_image - +from openerp.report.render.rml2pdf import customfonts + class multi_company_default(osv.osv): """ Manage multi company default value @@ -74,7 +75,7 @@ class res_company(osv.osv): _name = "res.company" _description = 'Companies' _order = 'name' - + def _get_address_data(self, cr, uid, ids, field_names, arg, context=None): """ Read the 'address' functional fields. """ result = {} @@ -108,9 +109,12 @@ class res_company(osv.osv): size = (180, None) result[record.id] = image_resize_image(record.partner_id.image, size) return result - + def _get_companies_from_partner(self, cr, uid, ids, context=None): return self.pool['res.company'].search(cr, uid, [('partner_id', 'in', ids)], context=context) + + def _get_font(self, cr, uid, context=None): + return sorted(customfonts.RegisterCustomFonts()) _columns = { 'name': fields.related('partner_id', 'name', string='Company Name', size=128, required=True, store=True, type='char'), @@ -124,6 +128,7 @@ class res_company(osv.osv): 'rml_footer': fields.text('Report Footer', help="Footer text displayed at the bottom of all reports."), 'rml_footer_readonly': fields.related('rml_footer', type='text', string='Report Footer', readonly=True), 'custom_footer': fields.boolean('Custom Footer', help="Check this to define the report footer manually. Otherwise it will be filled in automatically."), + 'font': fields.selection(_get_font, "Font",help="Set the font into the report header, will be used for every RML report of the company"), 'logo': fields.related('partner_id', 'image', string="Logo", type="binary"), 'logo_web': fields.function(_get_logo_web, string="Logo Web", type="binary", store={ 'res.company': (lambda s, c, u, i, x: i, ['partner_id'], 10), @@ -178,6 +183,21 @@ class res_company(osv.osv): if state_id: return {'value':{'country_id': self.pool.get('res.country.state').browse(cr, uid, state_id, context).country_id.id }} return {} + + def onchange_font_name(self, cr, uid, ids, font, rml_header, rml_header2, rml_header3, context=None): + """ To change default header style of all and drawstring. """ + + def _change_header(header,font): + """ Replace default fontname use in header and setfont tag """ + + default_para = re.sub('fontName.?=.?".*"', 'fontName="%s"'% font,header) + return re.sub('("%s"\g<3>'% font,default_para) + return {'value':{ + 'rml_header': _change_header(rml_header,font), + 'rml_header2':_change_header(rml_header2,font), + 'rml_header3':_change_header(rml_header3,font) + }} + def on_change_country(self, cr, uid, ids, country_id, context=None): res = {'domain': {'state_id': []}} currency_id = self._get_euro(cr, uid, context=context) @@ -374,7 +394,8 @@ class res_company(osv.osv): 'rml_header':_get_header, 'rml_header2': _header2, 'rml_header3': _header3, - 'logo':_get_logo + 'logo':_get_logo, + 'font':'Helvetica', } _constraints = [ diff --git a/openerp/addons/base/res/res_company_view.xml b/openerp/addons/base/res/res_company_view.xml index 52d97f37e02..e9acf7940b3 100644 --- a/openerp/addons/base/res/res_company_view.xml +++ b/openerp/addons/base/res/res_company_view.xml @@ -80,6 +80,7 @@ + diff --git a/openerp/report/render/rml2pdf/customfonts.py b/openerp/report/render/rml2pdf/customfonts.py index 85874f2b82f..ede2d91aaed 100644 --- a/openerp/report/render/rml2pdf/customfonts.py +++ b/openerp/report/render/rml2pdf/customfonts.py @@ -20,14 +20,13 @@ # ############################################################################## -import glob -import logging -import os -import platform from reportlab import rl_config +from reportlab.lib import fonts +from reportlab.pdfbase import pdfmetrics, ttfonts +import logging +import os,platform -from openerp.tools import config - +# .apidoc title: TTF Font Table """This module allows the mapping of some system-available TTF fonts to the reportlab engine. @@ -38,103 +37,127 @@ should have the same filenames, only need the code below). Due to an awful configuration that ships with reportlab at many Linux and Ubuntu distros, we have to override the search path, too. """ - +_fonts_cache = {'registered_fonts': [], 'total_system_fonts': 0} _logger = logging.getLogger(__name__) -CustomTTFonts = [ ('Helvetica',"DejaVu Sans", "DejaVuSans.ttf", 'normal'), - ('Helvetica',"DejaVu Sans Bold", "DejaVuSans-Bold.ttf", 'bold'), - ('Helvetica',"DejaVu Sans Oblique", "DejaVuSans-Oblique.ttf", 'italic'), - ('Helvetica',"DejaVu Sans BoldOblique", "DejaVuSans-BoldOblique.ttf", 'bolditalic'), - ('Times',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'), - ('Times',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'), - ('Times',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'), - ('Times',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'), - ('Times-Roman',"Liberation Serif", "LiberationSerif-Regular.ttf", 'normal'), - ('Times-Roman',"Liberation Serif Bold", "LiberationSerif-Bold.ttf", 'bold'), - ('Times-Roman',"Liberation Serif Italic", "LiberationSerif-Italic.ttf", 'italic'), - ('Times-Roman',"Liberation Serif BoldItalic", "LiberationSerif-BoldItalic.ttf", 'bolditalic'), - ('Courier',"FreeMono", "FreeMono.ttf", 'normal'), - ('Courier',"FreeMono Bold", "FreeMonoBold.ttf", 'bold'), - ('Courier',"FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'), - ('Courier',"FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'), - - # Sun-ExtA can be downloaded from http://okuc.net/SunWb/ - ('Sun-ExtA',"Sun-ExtA", "Sun-ExtA.ttf", 'normal'), +# Basic fonts familly included in PDF standart, will always be in the font list +BasePDFFonts = [ + ('Helvetica', 'Helvetica'), + ('Times', 'Times'), + ('Courier', 'Courier'), ] +# List of fonts found on the disk +CustomTTFonts = [] -TTFSearchPath_Linux = [ +# Search path for TTF files, in addition of rl_config.TTFSearchPath +TTFSearchPath = [ '/usr/share/fonts/truetype', # SuSE '/usr/share/fonts/dejavu', '/usr/share/fonts/liberation', # Fedora, RHEL - '/usr/share/fonts/truetype/*', # Ubuntu, + '/usr/share/fonts/truetype/*','/usr/local/share/fonts' # Ubuntu, '/usr/share/fonts/TTF/*', # at Mandriva/Mageia '/usr/share/fonts/TTF', # Arch Linux - ] + '/usr/lib/openoffice/share/fonts/truetype/', + '~/.fonts', + '~/.local/share/fonts', -TTFSearchPath_Windows = [ - 'c:/winnt/fonts', - 'c:/windows/fonts' - ] - -TTFSearchPath_Darwin = [ - #mac os X - from - #http://developer.apple.com/technotes/tn/tn2024.html + # mac os X - from + # http://developer.apple.com/technotes/tn/tn2024.html '~/Library/Fonts', '/Library/Fonts', '/Network/Library/Fonts', '/System/Library/Fonts', - ] -TTFSearchPathMap = { - 'Darwin': TTFSearchPath_Darwin, - 'Windows': TTFSearchPath_Windows, - 'Linux': TTFSearchPath_Linux, -} + # windows + 'c:/winnt/fonts', + 'c:/windows/fonts' +] -# ----- The code below is less distro-specific, please avoid editing! ------- -__foundFonts = None - -def FindCustomFonts(): - """Fill the __foundFonts list with those filenames, whose fonts - can be found in the reportlab ttf font path. - - This process needs only be done once per loading of this module, - it is cached. But, if the system admin adds some font in the - meanwhile, the server must be restarted eventually. +def all_sysfonts_list(): """ - dirpath = [] - global __foundFonts - __foundFonts = {} - searchpath = [] - - if config.get('fonts_search_path'): - searchpath += map(str.strip, config.get('fonts_search_path').split(',')) - - local_platform = platform.system() - if local_platform in TTFSearchPathMap: - searchpath += TTFSearchPathMap[local_platform] - - # Append the original search path of reportlab (at the end) - searchpath += rl_config.TTFSearchPath + This function returns list of font directories of system. + """ + filepath = [] # Perform the search for font files ourselves, as reportlab's # TTFOpenFile is not very good at it. - for dirglob in searchpath: - dirglob = os.path.expanduser(dirglob) - for dirname in glob.iglob(dirglob): - abp = os.path.abspath(dirname) - if os.path.isdir(abp): - dirpath.append(abp) + searchpath = list(set(TTFSearchPath + rl_config.TTFSearchPath)) + for dirname in searchpath: + dirname = os.path.expanduser(dirname) + if os.path.exists(dirname): + for filename in [x for x in os.listdir(dirname) if x.lower().endswith('.ttf')]: + filepath.append(os.path.join(dirname, filename)) + return filepath - for k, (name, font, filename, mode) in enumerate(CustomTTFonts): - if filename in __foundFonts: - continue - for d in dirpath: - abs_filename = os.path.join(d, filename) - if os.path.exists(abs_filename): - _logger.debug("Found font %s at %s", filename, abs_filename) - __foundFonts[filename] = abs_filename - break +def init_new_font(familyName, name, font_dir): + return { + 'regular':(familyName, name, font_dir, 'regular'), + 'italic':(), + 'bold':(familyName, name, font_dir, 'bold'), + 'bolditalic':(), + } + +def RegisterCustomFonts(): + """ + This function prepares a list for all system fonts to be registered + in reportlab and returns the updated list with new fonts. + """ + global CustomTTFonts + all_system_fonts = all_sysfonts_list() + if len(all_system_fonts) != _fonts_cache['total_system_fonts']: + font_modes, last_family, registered_font_list, _fonts_cache['registered_fonts'] = {}, "", [], list(BasePDFFonts) + + #Prepares a list of registered fonts. Remove such fonts those don't have cmap for Unicode. + for dirname in all_system_fonts: + try: + font_info = ttfonts.TTFontFile(dirname) + if font_info.styleName in ('Regular','Normal','Book','Medium', 'Roman'): + _fonts_cache['registered_fonts'].append((font_info.name, font_info.fullName)) + registered_font_list.append((font_info.familyName, font_info.name, dirname, font_info.styleName.lower().replace(" ", ""))) + _logger.debug("Found font %s at %s", font_info.name, dirname) + except: + _logger.warning("Could not register Font %s", dirname) + + #Prepare font list for mapping.Each font family requires four type of modes(regular,bold,italic,bolditalic). + #If all modes are not found, dummy entries are made for remaining modes. + for familyName, name, font_dir, mode in sorted(registered_font_list): + if not last_family or not font_modes: + last_family = familyName + font_modes = init_new_font(familyName, name, font_dir) + + if last_family != familyName: + # new font familly, adding previous to the list of fonts + if not font_modes['italic']: + font_modes['italic'] = font_modes['regular'][:3]+('italic',) + if not font_modes['bolditalic']: + font_modes['bolditalic'] = font_modes['bold'][:3]+('bolditalic',) + CustomTTFonts.extend(font_modes.values()) + font_modes = init_new_font(familyName, name, font_dir) + + if (mode== 'normal') or (mode == 'regular') or (mode == 'medium') or (mode == 'book') or (mode == 'roman'): + font_modes['regular'] = (familyName, name, font_dir, 'regular') + elif (mode == 'italic') or (mode == 'oblique'): + font_modes['italic'] = (familyName, name, font_dir, 'italic') + elif mode == 'bold': + font_modes['bold'] = (familyName, name, font_dir, 'bold') + elif (mode == 'bolditalic') or (mode == 'boldoblique'): + font_modes['bolditalic'] = (familyName, name, font_dir, 'bolditalic') + last_family = familyName + + # add the last one + if font_modes: + if not font_modes['italic']: + font_modes['italic'] = font_modes['regular'][:3]+('italic',) + if not font_modes['bolditalic']: + font_modes['bolditalic'] = font_modes['bold'][:3]+('bolditalic',) + CustomTTFonts.extend(font_modes.values()) + + _fonts_cache['total_system_fonts'] = len(all_system_fonts) + + # remove duplicates + CustomTTFonts = sorted(list(set(CustomTTFonts))) + _fonts_cache['registered_fonts'] = sorted(list(set(_fonts_cache['registered_fonts']))) + return _fonts_cache['registered_fonts'] def SetCustomFonts(rmldoc): """ Map some font names to the corresponding TTF fonts @@ -144,16 +167,11 @@ def SetCustomFonts(rmldoc): This function is called once per report, so it should avoid system-wide processing (cache it, instead). """ - global __foundFonts - if __foundFonts is None: - FindCustomFonts() + if not _fonts_cache['registered_fonts']: + RegisterCustomFonts() for name, font, filename, mode in CustomTTFonts: if os.path.isabs(filename) and os.path.exists(filename): rmldoc.setTTFontMapping(name, font, filename, mode) - elif filename in __foundFonts: - rmldoc.setTTFontMapping(name, font, __foundFonts[filename], mode) return True -#eof - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: