From 0da34c04e5955e73dee1bb55941145ebb572f971 Mon Sep 17 00:00:00 2001 From: Dave Ankin Date: Tue, 1 Dec 2020 01:37:42 -0500 Subject: [PATCH] start progress adding test for fonts --- fpdf/errors.py | 22 +++++++- fpdf/fpdf.py | 10 +++- fpdf/util/__init__.py | 3 +- test/fonts/NotoSansShavian-Regular.ttf | Bin 0 -> 7876 bytes test/fonts/__init__.py | 4 ++ test/fonts/respect_user_path.py | 72 +++++++++++++++++++++++++ test/fonts/slick.ttf | Bin 0 -> 1892 bytes 7 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 test/fonts/NotoSansShavian-Regular.ttf create mode 100644 test/fonts/__init__.py create mode 100644 test/fonts/respect_user_path.py create mode 100644 test/fonts/slick.ttf diff --git a/fpdf/errors.py b/fpdf/errors.py index c3b9cfa77..0c7f71aea 100644 --- a/fpdf/errors.py +++ b/fpdf/errors.py @@ -7,11 +7,14 @@ def fpdf_error(message): raise RuntimeError('FPDF error: ' + message) +def argument_representation(inputs): + return ', '.join(list(map(lambda x: repr(x), inputs))) + class FPDFException(Exception): pass class FPDFPageFormatException(FPDFException): - # """Error is thrown when a bad page format is given""" + """Error is thrown when a bad page format is given""" def __init__(self, argument, unknown=False, one=False): super(FPDFPageFormatException, self).__init__() @@ -34,7 +37,7 @@ def format_one(self, a): def __repr__(self): inputs = [self.argument, self.unknown, self.one] - arguments = ', '.join(list(map(lambda x: repr(x), inputs))) + arguments = argument_representation(inputs) return ''.join(['FPDFPageFormatException(', arguments, ')']) def __str__(self): @@ -45,3 +48,18 @@ def __str__(self): else: return self._f(self.argument) +class FPDFUndefinedFontException(FPDFException): + """Error is thrown when set_font called on font which is not added""" + def __init__(self, family, style): + super(FPDFUndefinedFontException, self).__init__() + self.family = family + self.style = style + + def __repr__(self): + arguments = argument_representation([self.family, self.style]) + return 'FPDFUndefinedFontException({})'.format(arguments) + + def __str__(self): + style = ' ' + self.style if self.style and len(self.style) else '' + return 'Undefined font: {}{}'.format(self.family, style) + \ No newline at end of file diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 916f34e31..155b92224 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -37,7 +37,8 @@ from .errors import ( fpdf_error, FPDFException, - FPDFPageFormatException + FPDFPageFormatException, + FPDFUndefinedFontException ) from .fonts import fpdf_charwidths from .image_parsing import ( @@ -173,6 +174,7 @@ def __init__(self, orientation = 'P', unit = 'mm', format = 'A4'): 'timesBI': 'Times-BoldItalic', 'symbol': 'Symbol', 'zapfdingbats': 'ZapfDingbats'} self.core_fonts_encoding = "latin-1" + self.unifontsubset = True # Scale factor if unit == "pt": @@ -220,6 +222,8 @@ def __init__(self, orientation = 'P', unit = 'mm', format = 'A4'): self.set_compression(1) # Enable compression self.pdf_version = '1.3' # Set default PDF version No. + self.set_font('arial', '', 12) + def check_page(fn): "Decorator to protect drawing methods" @wraps(fn) @@ -549,6 +553,7 @@ def add_font(self, family, style = '', fname = None, uni = False): if (style == 'IB'): style = 'BI' fontkey = family + style + print(fontkey, fontkey in self.fonts, uni, 'looking in', fname, os.path.join(FPDF_FONT_DIR, fname)) # Font already added! if fontkey in self.fonts: return if (uni): @@ -710,7 +715,7 @@ def set_font(self, family, style='', size=0): 'cw' : fpdf_charwidths[fontkey] } else: - fpdf_error('Undefined font: ' + family + ' ' + style) + raise FPDFUndefinedFontException(family, style) # Select it self.font_family = family @@ -919,6 +924,7 @@ def cell(self, w, h = 0, txt = '', border = 0, ln = 0, align = '', s += ' ET' else: if (self.unifontsubset): + # txt2 = escape_parens(UTF8ToUTF16BE(txt, False)) for uni in UTF8StringToArray(txt): self.current_font['subset'].append(uni) diff --git a/fpdf/util/__init__.py b/fpdf/util/__init__.py index 7526c3ac3..9857120c8 100644 --- a/fpdf/util/__init__.py +++ b/fpdf/util/__init__.py @@ -21,7 +21,8 @@ def textstring(s): def escape(s): "Add \ before \, ( and )" - return s.replace('\\', '\\\\') \ + # return s.replace('\\', '\\\\') \ + return str(s).replace('\\', '\\\\') \ .replace(')', '\\)') \ .replace('(', '\\(') \ .replace('\r', '\\r') diff --git a/test/fonts/NotoSansShavian-Regular.ttf b/test/fonts/NotoSansShavian-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9358fcb6bb10e07be8b098c6cda4efd707ce6c34 GIT binary patch literal 7876 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 literal 0 HcmV?d00001