diff --git a/openerp/addons/base/base_data.xml b/openerp/addons/base/base_data.xml
index 6a47325db39..bd38f3a3db5 100644
--- a/openerp/addons/base/base_data.xml
+++ b/openerp/addons/base/base_data.xml
@@ -91,5 +91,25 @@ Administrator
+
+
+ Helvetica
+ Helvetica
+ /dev/null
+ all
+
+
+ Times
+ Times
+ /dev/null
+ all
+
+
+ Courier
+ Courier
+ /dev/null
+ all
+
+
diff --git a/openerp/addons/base/report/custom_default_printscreen.xsl b/openerp/addons/base/report/custom_default_printscreen.xsl
index b8b30222953..de787f2bdef 100644
--- a/openerp/addons/base/report/custom_default_printscreen.xsl
+++ b/openerp/addons/base/report/custom_default_printscreen.xsl
@@ -5,9 +5,9 @@
-
+
-
+
1.3cm 19.3cm 28.5cm 19.3cm
diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py
index 6e74dbf1547..b46492d28d7 100644
--- a/openerp/addons/base/res/res_company.py
+++ b/openerp/addons/base/res/res_company.py
@@ -27,7 +27,6 @@ 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):
"""
@@ -183,17 +182,20 @@ class res_company(osv.osv):
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)
+ default_para = re.sub('fontName.?=.?".*"', 'fontName="%s"'% font, header)
+ return re.sub('("%s"\g<3>'% font, default_para)
+
+ if not font:
+ return True
fontname = self.pool.get('res.font').browse(cr, uid, font, context=context).name
return {'value':{
- 'rml_header': _change_header(rml_header,fontname),
- 'rml_header2':_change_header(rml_header2,fontname),
- 'rml_header3':_change_header(rml_header3,fontname)
+ 'rml_header': _change_header(rml_header, fontname),
+ 'rml_header2':_change_header(rml_header2, fontname),
+ 'rml_header3':_change_header(rml_header3, fontname)
}}
def on_change_country(self, cr, uid, ids, country_id, context=None):
@@ -294,12 +296,8 @@ class res_company(osv.osv):
def _get_font(self, cr, uid, ids):
font_obj = self.pool.get('res.font')
- res = font_obj.search(cr, uid, [('name', '=', 'Helvetica')], limit=1)
- if res:
- return res[0]
-
- font_obj.init_no_scan(cr, uid)
- return font_obj.search(cr, uid, [('name', '=', 'Helvetica')], limit=1)[0]
+ res = font_obj.search(cr, uid, [('family', '=', 'Helvetica'), ('mode', '=', 'all')], limit=1)
+ return res and res[0] or False
_header = """
@@ -307,20 +305,20 @@ class res_company(osv.osv):
-
+
-
+
[[ formatLang(time.strftime("%%Y-%%m-%%d"), date=True) ]] [[ time.strftime("%%H:%%M") ]]
-
+
[[ company.partner_id.name ]]
%s
-
+
"""
@@ -345,13 +343,13 @@ class res_company(osv.osv):
-
+
-
+
[[ company.logo or removeParentNode('image') ]]
@@ -396,7 +394,7 @@ class res_company(osv.osv):
return {'value': {'rml_header': self._header_a4}}
def act_discover_fonts(self, cr, uid, ids, context=None):
- return self.pool.get("res.font").discover_fonts(cr, uid, ids, context)
+ return self.pool.get("res.font").font_scan(cr, uid, context=context)
_defaults = {
'currency_id': _get_euro,
diff --git a/openerp/addons/base/res/res_company_view.xml b/openerp/addons/base/res/res_company_view.xml
index 3fccba944f9..c037b0e76ac 100644
--- a/openerp/addons/base/res/res_company_view.xml
+++ b/openerp/addons/base/res/res_company_view.xml
@@ -85,7 +85,7 @@
diff --git a/openerp/addons/base/res/res_font.py b/openerp/addons/base/res/res_font.py
index 4218b0b7955..306a8944783 100644
--- a/openerp/addons/base/res/res_font.py
+++ b/openerp/addons/base/res/res_font.py
@@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2009 Tiny SPRL ().
+# Copyright (C) 2013 OpenERP SA ().
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -20,6 +20,7 @@
##############################################################################
from reportlab.pdfbase import ttfonts
+from openerp.modules.registry import RegistryManager
from openerp.osv import fields, osv
from openerp.report.render.rml2pdf import customfonts
@@ -40,57 +41,75 @@ _logger = logging.getLogger(__name__)
class res_font(osv.Model):
_name = "res.font"
_description = 'Fonts available'
- _order = 'name'
+ _order = 'family,name,id'
+ _rec_name = 'family'
_columns = {
- 'name': fields.char("Name", required=True),
+ 'family': fields.char("Font family", required=True),
+ 'name': fields.char("Font Name", required=True),
+ 'path': fields.char("Path", required=True),
+ 'mode': fields.char("Mode", required=True),
}
_sql_constraints = [
- ('name_font_uniq', 'unique(name)', 'You can not register two fonts with the same name'),
+ ('name_font_uniq', 'unique(family, name)', 'You can not register two fonts with the same name'),
]
- def discover_fonts(self, cr, uid, ids, context=None):
- """Scan fonts on the file system, add them to the list of known fonts
- and create font object for the new ones"""
- customfonts.CustomTTFonts = customfonts.BaseCustomTTFonts
+ def font_scan(self, cr, uid, lazy=False, context=None):
+ """Action of loading fonts
+ In lazy mode will scan the filesystem only if there is no founts in the database and sync if no font in CustomTTFonts
+ In not lazy mode will force scan filesystem and sync
+ """
+ if lazy:
+ # lazy loading, scan only if no fonts in db
+ found_fonts_ids = self.search(cr, uid, [('path', '!=', '/dev/null')], context=context)
+ if not found_fonts_ids:
+ # no scan yet or no font found on the system, scan the filesystem
+ self._scan_disk(cr, uid, context=context)
+ elif len(customfonts.CustomTTFonts) == 0:
+ # CustomTTFonts list is empty
+ self._sync(cr, uid, context=context)
+ else:
+ self._scan_disk(cr, uid, context=context)
+ return True
- found_fonts = {}
+ def _scan_disk(self, cr, uid, context=None):
+ """Scan the file system and register the result in database"""
+ found_fonts = []
for font_path in customfonts.list_all_sysfonts():
try:
font = ttfonts.TTFontFile(font_path)
_logger.debug("Found font %s at %s", font.name, font_path)
- if not found_fonts.get(font.familyName):
- found_fonts[font.familyName] = {'name': font.familyName}
-
- mode = font.styleName.lower().replace(" ", "")
-
- customfonts.CustomTTFonts.append((font.familyName, font.name, font_path, mode))
+ found_fonts.append((font.familyName, font.name, font_path, font.styleName))
except ttfonts.TTFError:
_logger.warning("Could not register Font %s", font_path)
- # add default PDF fonts
- for family in customfonts.BasePDFFonts:
- if not found_fonts.get(family):
- found_fonts[family] = {'name': family}
+ for family, name, path, mode in found_fonts:
+ if not self.search(cr, uid, [('family', '=', family), ('name', '=', name)], context=context):
+ self.create(cr, uid, {
+ 'family': family, 'name': name,
+ 'path': path, 'mode': mode,
+ }, context=context)
- # remove deleted fonts
- existing_font_ids = self.search(cr, uid, [], context=context)
- existing_font_names = []
- for font in self.browse(cr, uid, existing_font_ids):
- existing_font_names.append(font.name)
- if font.name not in found_fonts.keys():
- self.unlink(cr, uid, font.id, context=context)
+ # remove fonts not present on the disk anymore
+ existing_font_names = [name for (family, name, path, mode) in found_fonts]
+ inexistant_fonts = self.search(cr, uid, [('name', 'not in', existing_font_names), ('path', '!=', '/dev/null')], context=context)
+ if inexistant_fonts:
+ self.unlink(cr, uid, inexistant_fonts, context=context)
- # add unknown fonts
- for family, vals in found_fonts.items():
- if family not in existing_font_names:
- self.create(cr, uid, vals, context=context)
+ RegistryManager.signal_caches_change(cr.dbname)
+ self._sync(cr, uid, context=context)
return True
- def init_no_scan(self, cr, uid, context=None):
- """Add demo data for PDF fonts without scan (faster for db creation)"""
- for font in customfonts.BasePDFFonts:
- if not self.search(cr, uid, [('name', '=', font)], context=context):
- self.create(cr, uid, {'name':font}, context=context)
- return True
\ No newline at end of file
+ def _sync(self, cr, uid, context=None):
+ """Set the customfonts.CustomTTFonts list to the content of the database"""
+ customfonts.CustomTTFonts = []
+ found_fonts_ids = self.search(cr, uid, [('path', '!=', '/dev/null')], context=context)
+ for font in self.browse(cr, uid, found_fonts_ids, context=None):
+ customfonts.CustomTTFonts.append((font.family, font.name, font.path, font.mode))
+ return True
+
+ def clear_caches(self):
+ """Force worker to resync at next report loading by setting an empty font list"""
+ customfonts.CustomTTFonts = []
+ return super(res_font, self).clear_caches()
\ No newline at end of file
diff --git a/openerp/addons/base/security/ir.model.access.csv b/openerp/addons/base/security/ir.model.access.csv
index 167c18ae884..cb391a45701 100644
--- a/openerp/addons/base/security/ir.model.access.csv
+++ b/openerp/addons/base/security/ir.model.access.csv
@@ -43,6 +43,8 @@
"access_ir_values_group_all","ir_values group_all","model_ir_values",,1,1,1,1
"access_res_company_group_erp_manager","res_company group_erp_manager","model_res_company","group_erp_manager",1,1,1,1
"access_res_company_group_user","res_company group_user","model_res_company",,1,0,0,0
+"access_res_font_group_erp_manager","res_font group_erp_manager","model_res_font","group_erp_manager",1,1,1,1
+"access_res_font_group_all","res_font group_all","model_res_font",,1,0,0,0
"access_res_country_group_all","res_country group_user_all","model_res_country",,1,0,0,0
"access_res_country_state_group_all","res_country_state group_user_all","model_res_country_state",,1,0,0,0
"access_res_country_group_user","res_country group_user","model_res_country","group_partner_manager",1,1,1,1
diff --git a/openerp/report/interface.py b/openerp/report/interface.py
index 846172ef773..6a20a63ef34 100644
--- a/openerp/report/interface.py
+++ b/openerp/report/interface.py
@@ -24,8 +24,6 @@ import re
from lxml import etree
-import openerp
-
import openerp
import openerp.tools as tools
import openerp.modules
@@ -33,6 +31,9 @@ import print_xml
import render
import urllib
+from openerp import SUPERUSER_ID
+from openerp.report.render.rml2pdf import customfonts
+
#
# coerce any type to a unicode string (to preserve non-ascii characters)
# and escape XML entities
@@ -91,13 +92,16 @@ class report_rml(report_int):
}
def create(self, cr, uid, ids, datas, context):
+ registry = openerp.registry(cr.dbname)
xml = self.create_xml(cr, uid, ids, datas, context)
xml = tools.ustr(xml).encode('utf8')
report_type = datas.get('report_type', 'pdf')
if report_type == 'raw':
return xml, report_type
+
+ registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context)
+
rml = self.create_rml(cr, xml, uid, context)
- registry = openerp.registry(cr.dbname)
ir_actions_report_xml_obj = registry['ir.actions.report.xml']
report_xml_ids = ir_actions_report_xml_obj.search(cr, uid, [('report_name', '=', self.name[7:])], context=context)
self.title = report_xml_ids and ir_actions_report_xml_obj.browse(cr,uid,report_xml_ids)[0].name or 'OpenERP Report'
diff --git a/openerp/report/render/rml2pdf/customfonts.py b/openerp/report/render/rml2pdf/customfonts.py
index 7f89f324bf7..a54359b4f0b 100644
--- a/openerp/report/render/rml2pdf/customfonts.py
+++ b/openerp/report/render/rml2pdf/customfonts.py
@@ -21,10 +21,9 @@
##############################################################################
from reportlab import rl_config
-from reportlab.lib import fonts
-from reportlab.pdfbase import pdfmetrics, ttfonts
import logging
-import os,platform
+import glob
+import os
# .apidoc title: TTF Font Table
@@ -39,35 +38,14 @@ and Ubuntu distros, we have to override the search path, too.
"""
_logger = logging.getLogger(__name__)
-# Basic fonts family included in PDF standart, will always be in the font list
-BasePDFFonts = [
- 'Helvetica',
- 'Times',
- 'Courier'
-]
-
-# List of fonts found on the disk
-CustomTTFonts = BaseCustomTTFonts = [ ('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'),
- ('Courier', "FreeMono", "FreeMono.ttf", 'normal'),
- ('Courier', "FreeMono Bold", "FreeMonoBold.ttf", 'bold'),
- ('Courier', "FreeMono Oblique", "FreeMonoOblique.ttf", 'italic'),
- ('Courier', "FreeMono BoldOblique", "FreeMonoBoldOblique.ttf", 'bolditalic'),
-]
-
+CustomTTFonts = []
# 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/*','/usr/local/share/fonts' # Ubuntu,
- '/usr/share/fonts/TTF/*', # at Mandriva/Mageia
+ '/usr/share/fonts/TTF/*', # Mandriva/Mageia
'/usr/share/fonts/TTF', # Arch Linux
'/usr/lib/openoffice/share/fonts/truetype/',
'~/.fonts',
@@ -95,10 +73,8 @@ def list_all_sysfonts():
# TTFOpenFile is not very good at it.
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))
+ for filename in glob.glob(os.path.join(os.path.expanduser(dirname), '*.[Tt][Tt][Ff]')):
+ filepath.append(filename)
return filepath
def SetCustomFonts(rmldoc):
@@ -109,9 +85,9 @@ def SetCustomFonts(rmldoc):
This function is called once per report, so it should
avoid system-wide processing (cache it, instead).
"""
- for name, font, filename, mode in CustomTTFonts:
+ for family, font, filename, mode in CustomTTFonts:
if os.path.isabs(filename) and os.path.exists(filename):
- rmldoc.setTTFontMapping(name, font, filename, mode)
+ rmldoc.setTTFontMapping(family, font, filename, mode)
return True
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py
index b075b0f53ea..ad1ff656e1d 100644
--- a/openerp/report/render/rml2pdf/trml2pdf.py
+++ b/openerp/report/render/rml2pdf/trml2pdf.py
@@ -56,8 +56,11 @@ def select_fontname(fontname, default_fontname):
try:
pdfmetrics.getFont(fontname)
except Exception:
- _logger.warning('Could not locate font %s, substituting default: %s',
- fontname, default_fontname)
+ addition = ""
+ if " " in fontname:
+ addition = ". Your font contains spaces which is not valid in RML."
+ _logger.warning('Could not locate font %s, substituting default: %s%s',
+ fontname, default_fontname, addition)
fontname = default_fontname
return fontname
@@ -307,7 +310,7 @@ class _rml_doc(object):
addMapping(face, 0, 1, fontname) #italic
addMapping(face, 1, 0, fontname) #bold
addMapping(face, 1, 1, fontname) #italic and bold
- elif (mode== 'normal') or (mode == 'regular'):
+ elif (mode== 'normal') or (mode == 'regular') or (mode == 'book'):
addMapping(face, 0, 0, fontname) #normal
elif mode == 'italic':
addMapping(face, 0, 1, fontname) #italic
diff --git a/openerp/report/report_sxw.py b/openerp/report/report_sxw.py
index 548a3f833f5..03bc0ffa03f 100644
--- a/openerp/report/report_sxw.py
+++ b/openerp/report/report_sxw.py
@@ -34,6 +34,7 @@ import zipfile
import common
import openerp
+from openerp import SUPERUSER_ID
from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
@@ -419,10 +420,13 @@ class report_sxw(report_rml, preprocess.report):
context = {}
if self.internal_header:
context.update(internal_header=self.internal_header)
+
# skip osv.fields.sanitize_binary_value() because we want the raw bytes in all cases
context.update(bin_raw=True)
registry = openerp.registry(cr.dbname)
ir_obj = registry['ir.actions.report.xml']
+ registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context)
+
report_xml_ids = ir_obj.search(cr, uid,
[('report_name', '=', self.name[7:])], context=context)
if report_xml_ids: