[FIX] font: cleaning and better default data

bzr revid: mat@openerp.com-20131014123815-6tnegdiv4cnaimtf
This commit is contained in:
Martin Trigaux 2013-10-14 14:38:15 +02:00
parent 3798b1ed96
commit 53e8625cea
4 changed files with 49 additions and 154 deletions

View File

@ -25,11 +25,11 @@ import res_partner
import res_bank
import res_config
import res_currency
import res_font
import res_company
import res_users
import res_request
import res_lang
import res_font
import ir_property
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -292,6 +292,15 @@ class res_company(osv.osv):
def _get_logo(self, cr, uid, ids):
return open(os.path.join( tools.config['root_path'], 'addons', 'base', 'res', 'res_company_logo.png'), 'rb') .read().encode('base64')
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]
_header = """
<header>
<pageTemplate>
@ -396,6 +405,7 @@ class res_company(osv.osv):
'rml_header2': _header2,
'rml_header3': _header3,
'logo':_get_logo,
'font':_get_font,
}
_constraints = [

View File

@ -19,12 +19,11 @@
#
##############################################################################
from reportlab import rl_config
from reportlab.pdfbase import pdfmetrics, ttfonts
from reportlab.pdfbase import ttfonts
from openerp.osv import fields, osv
from openerp.report.render.rml2pdf import customfonts
import logging
import os,platform
"""This module allows the mapping of some system-available TTF fonts to
the reportlab engine.
@ -35,72 +34,8 @@ 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__)
# 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'),
]
# Search path for TTF files, in addition of rl_config.TTFSearchPath
TTFSearchPath = [
'~/test',
'/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', # Arch Linux
'/usr/lib/openoffice/share/fonts/truetype/',
'~/.fonts',
'~/.local/share/fonts',
# mac os X - from
# http://developer.apple.com/technotes/tn/tn2024.html
'~/Library/Fonts',
'/Library/Fonts',
'/Network/Library/Fonts',
'/System/Library/Fonts',
# windows
'c:/winnt/fonts',
'c:/windows/fonts'
]
def list_all_sysfonts():
"""
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.
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
class res_font(osv.Model):
_name = "res.font"
@ -112,14 +47,16 @@ class res_font(osv.Model):
}
_sql_constraints = [
('name_font_uniq', 'unique(name)', 'You can not register to fonts with the same name'),
('name_font_uniq', 'unique(name)', 'You can not register two fonts with the same name'),
]
def act_discover_fonts(self, cr, uid, ids, context=None):
CustomTTFonts = BaseCustomTTFonts
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
found_fonts = {}
for font_path in list_all_sysfonts():
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)
@ -128,12 +65,12 @@ class res_font(osv.Model):
mode = font.styleName.lower().replace(" ", "")
CustomTTFonts.append((font.familyName, font.name, font_path, mode))
customfonts.CustomTTFonts.append((font.familyName, font.name, font_path, mode))
except ttfonts.TTFError:
_logger.warning("Could not register Font %s", font_path)
# add default PDF fonts
for family in BasePDFFonts:
for family in customfonts.BasePDFFonts:
if not found_fonts.get(family):
found_fonts[family] = {'name': family}
@ -141,5 +78,13 @@ class res_font(osv.Model):
# to make sure we always have updated list, delete all and recreate
self.unlink(cr, uid, self.search(cr, uid, [], context=context), context=context)
for family, vals in found_fonts.items():
self.create(cr, uid, vals, context=context)
if not self.search(cr, uid, [('name', '=', family)], context=context):
self.create(cr, uid, vals, 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

View File

@ -37,18 +37,30 @@ 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__)
# Basic fonts familly included in PDF standart, will always be in the font list
# Basic fonts family included in PDF standart, will always be in the font list
BasePDFFonts = [
('Helvetica', 'Helvetica'),
('Times', 'Times'),
('Courier', 'Courier'),
'Helvetica',
'Times',
'Courier'
]
# List of fonts found on the disk
CustomTTFonts = []
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'),
]
# Search path for TTF files, in addition of rl_config.TTFSearchPath
TTFSearchPath = [
@ -73,7 +85,7 @@ TTFSearchPath = [
'c:/windows/fonts'
]
def all_sysfonts_list():
def list_all_sysfonts():
"""
This function returns list of font directories of system.
"""
@ -89,76 +101,6 @@ def all_sysfonts_list():
filepath.append(os.path.join(dirname, filename))
return filepath
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
@ -167,8 +109,6 @@ def SetCustomFonts(rmldoc):
This function is called once per report, so it should
avoid system-wide processing (cache it, instead).
"""
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)