-
-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
890961d
commit ff03f8b
Showing
56 changed files
with
371 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
""" | ||
The TrueType font format was developed by Apple Computer, Inc., and has been adopted as a standard font | ||
format for the Microsoft Windows operating system. Specifications for the TrueType font file format are | ||
available in Apple’s TrueType Reference Manual and Microsoft’s TrueType 1.0 Font Files Technical | ||
Specification (see Bibliography). | ||
""" | ||
import json | ||
import os | ||
import tempfile | ||
import typing | ||
import pathlib | ||
|
||
import requests | ||
|
||
from borb.pdf.canvas.font.simple_font.true_type_font import TrueTypeFont | ||
|
||
|
||
class GoogleTrueTypeFont(TrueTypeFont): | ||
""" | ||
A TrueType font dictionary may contain the same entries as a Type 1 font dictionary (see Table 111), with these | ||
differences: | ||
• The value of Subtype shall be TrueType. | ||
• The value of Encoding is subject to limitations that are described in 9.6.6, "Character Encoding". | ||
• The value of BaseFont is derived differently. The PostScript name for the value of BaseFont may be determined in one of two ways: | ||
• If the TrueType font program's “name” table contains a PostScript name, it shall be used. | ||
• In the absence of such an entry in the “name” table, a PostScript name shall be derived from the name by | ||
which the font is known in the host operating system. On a Windows system, the name shall be based on | ||
the lfFaceName field in a LOGFONT structure; in the Mac OS, it shall be based on the name of the FOND | ||
resource. If the name contains any SPACEs, the SPACEs shall be removed. | ||
""" | ||
|
||
# | ||
# CONSTRUCTOR | ||
# | ||
|
||
# | ||
# PRIVATE | ||
# | ||
|
||
@staticmethod | ||
def _download_google_font(font_name: str) -> pathlib.Path: | ||
|
||
# get GOOGLE_FONTS_API_KEY | ||
google_fonts_api_key: typing.Optional[str] = os.environ.get( | ||
"GOOGLE_FONTS_API_KEY" | ||
) | ||
assert ( | ||
google_fonts_api_key is not None | ||
), "GOOGLE_FONTS_API_KEY not found in os.environ" | ||
|
||
# download overview | ||
try: | ||
|
||
# list all items | ||
items: typing.List[typing.Dict] = json.loads( | ||
requests.get( | ||
f"https://www.googleapis.com/webfonts/v1/webfonts?key={google_fonts_api_key}" | ||
).content | ||
).get("items", []) | ||
|
||
# find matching font_info_dictionary | ||
font_info_dictionary: typing.Dict[str, typing.Any] = next( | ||
iter([x for x in items if x.get("family", None) == font_name]), None | ||
) | ||
assert font_info_dictionary is not None, f"Unable to find font {font_name}" | ||
|
||
# get URL | ||
true_type_font_file_url: typing.Optional[str] = font_info_dictionary.get( | ||
"files", {} | ||
).get("regular", None) | ||
assert ( | ||
true_type_font_file_url is not None | ||
), f"Unable to find URL for font {font_name}" | ||
|
||
# download to temporary file | ||
temp_font_file: pathlib.Path = pathlib.Path(tempfile.NamedTemporaryFile(suffix=".ttf").name) | ||
with open(temp_font_file, "wb") as fh: | ||
fh.write(requests.get(true_type_font_file_url).content) | ||
|
||
# return | ||
return temp_font_file | ||
except: | ||
assert False, f"Unable to process font {font_name}" | ||
|
||
# | ||
# PUBLIC | ||
# | ||
|
||
@staticmethod | ||
def true_type_font_from_google( | ||
font_name: str, | ||
) -> typing.Union["TrueTypeFont", "Type0Font"]: | ||
""" | ||
This function returns the PDF TrueTypeFont object for a given font name. | ||
It does so by looking up the font using the Google Fonts API, | ||
downloading the font to a temporary file, | ||
and subsequently loading that temporary file using TrueTypeFont.true_type_font_from_file | ||
:param font_name: the font name | ||
:return: a TrueTypeFont or Type0Font | ||
""" | ||
return TrueTypeFont.true_type_font_from_file( | ||
GoogleTrueTypeFont._download_google_font(font_name) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,18 @@ | ||
|
||
# :mega: borb release notes | ||
|
||
This release features `A4PortraitResumeTemplate` which offers a convenient way of making a resume. | ||
This release features `GoogleTrueTypeFont` which enables users to access the Google Font API, | ||
to directly use a `TrueTypeFont` in `borb` by specifying its name. | ||
|
||
Tests have been added for this feature: | ||
|
||
- `test_add_paragraphs_using_jacquard_12` | ||
- `test_add_paragraphs_using_pacifico` | ||
- `test_add_paragraphs_using_shadows_into_light` | ||
|
||
Some tests have been added to guard code quality: | ||
|
||
- `TestCodeFilesAreSmall` | ||
- `TestCodeFilesContainVisibilityCommentBlocks` | ||
- `TestCodeFilesStartWithPythonBash` | ||
- `TestCodeFilesUseFullyQualifiedBorbImports` | ||
- `TestCodeFilesUseKnownExternalImports` | ||
- `TestCodeFilesUseSingleLineImports` | ||
- `TestCodeFilesContainSortedMethods` | ||
- `TestCodeFilesContainVisibilityComments` | ||
- `TestCodeFilesDoNotContainNumbersInMethods` | ||
- `TestCodeFilesNeverUseKeyring` |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
{ | ||
"anonymous_user_id": "Joris Schellekens", | ||
"company": "borb (EZ)", | ||
"valid_from_as_str": "2024-05-04 00:35:59", | ||
"valid_until_as_str": "2024-05-11 00:35:59", | ||
"license_key": "P5yPQlUVr8ub0/TdH5vS+FGl3FGM3ZtBXQkWT6vQm4lQIE+jQjGf/ZMd8nACHAtfAL7JLC5PoPMAgvBPuj8RhxW7E8k3aG2bQVqG8pvQajl/o+hXpAv8Nlh4h/Ug3YNDnfxQBxACNdQnhYOv1GOpsVbYkWvjppifTs9KiE+BOc4TxtlxVYFaBtb90HdOxpx00nbRORlkz9ID0/ZYMhXMaNo8BkXHC60orbnS05V03PbfjQswW/G+MJ7hBmhxouW4cxWdhrE1/ReIoqrDIkZvu6Wl7lrLIzyYbbSkpTykoCyQkHXCgnTstUwfeE1Ou4sZmbdSpeZEtu6UzBAWe52NVg==" | ||
"valid_from_as_str": "2024-06-16 19:24:45", | ||
"valid_until_as_str": "2024-06-23 19:24:45", | ||
"license_key": "d3V8jPaCN7OPrLqmyTjnRWBQEs5fe1/NodIFf11Qq/LKVQHS58+5pkJ7wI2RlkIG27o6SlznCSuH9le5+O2Wn79UVGFxbWk0IrqIN8c5vWZlF8Jydd55UQcc5EXxyMzNxvVBSja7vcplUr6CB3yMjLTbJN9iM8QLTb0p7SBXjRqurT9+33VQLgGZeQBcsyEZnUTZW2CF5LqbB+fIGAyIG4CeCtp0mmsTx5LDwyGJnje/zFvk9qoMsLEyDJdPEWNTmWtSoz39nq4MpYuD/LEjB9NIXEgnxQgA9S5OGV+wvZxWlJlpMDZdXV57WjsN0ynVIFwVAsCvXIR+70eETxasEA==" | ||
} |
Binary file added
BIN
+10.2 KB
...nt/artifacts_test_add_paragraphs_using_google_fonts/output_001_ground_truth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+10.8 KB
...nt/artifacts_test_add_paragraphs_using_google_fonts/output_002_ground_truth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+10.2 KB
...nt/artifacts_test_add_paragraphs_using_google_fonts/output_003_ground_truth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
139 changes: 139 additions & 0 deletions
139
tests/pdf/canvas/font/test_add_paragraphs_using_google_fonts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
from decimal import Decimal | ||
|
||
from borb.pdf import Document | ||
from borb.pdf import FixedColumnWidthTable | ||
from borb.pdf import GoogleTrueTypeFont | ||
from borb.pdf import PDF | ||
from borb.pdf import Page | ||
from borb.pdf import PageLayout | ||
from borb.pdf import Paragraph | ||
from borb.pdf import SingleColumnLayout | ||
from borb.pdf import Table | ||
from borb.pdf import TrueTypeFont | ||
from tests.test_case import TestCase | ||
|
||
|
||
class TestAddParagraphsUsingGoogleFonts(TestCase): | ||
""" | ||
This test loads a truetype _font from a .ttf file and attempts to use it to write 2 paragraphs of lorem ipsum. | ||
""" | ||
|
||
def _write_document_with_font( | ||
self, | ||
font_name: str, | ||
) -> Document: | ||
|
||
# create document | ||
pdf = Document() | ||
|
||
# add page | ||
page = Page() | ||
pdf.add_page(page) | ||
|
||
# layout | ||
layout: PageLayout = SingleColumnLayout(page) | ||
|
||
# add test information | ||
layout.add( | ||
self.get_test_header( | ||
f"This test loads {font_name} from a file and attempts to write letters and numbers with it." | ||
) | ||
) | ||
|
||
# load font | ||
ttf: TrueTypeFont = GoogleTrueTypeFont.true_type_font_from_google(font_name) | ||
|
||
# add paragraph 1 | ||
uppercase_letter_table: Table = FixedColumnWidthTable( | ||
number_of_columns=5, number_of_rows=6 | ||
) | ||
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": | ||
try: | ||
uppercase_letter_table.add(Paragraph(c, font=ttf)) | ||
except: | ||
uppercase_letter_table.add(Paragraph("")) | ||
uppercase_letter_table.set_padding_on_all_cells( | ||
Decimal(2), Decimal(2), Decimal(2), Decimal(2) | ||
) | ||
layout.add(Paragraph("Uppercase:")) | ||
layout.add(uppercase_letter_table) | ||
|
||
# lowercase | ||
lowercase_letter_table: Table = FixedColumnWidthTable( | ||
number_of_columns=5, number_of_rows=6 | ||
) | ||
for c in "abcdefghijklmnopqrstuvwxyz": | ||
try: | ||
lowercase_letter_table.add(Paragraph(c, font=ttf)) | ||
except: | ||
lowercase_letter_table.add(Paragraph("")) | ||
lowercase_letter_table.set_padding_on_all_cells( | ||
Decimal(2), Decimal(2), Decimal(2), Decimal(2) | ||
) | ||
layout.add(Paragraph("Lowercase:")) | ||
layout.add(lowercase_letter_table) | ||
|
||
# lowercase | ||
digit_table: Table = FixedColumnWidthTable( | ||
number_of_columns=5, number_of_rows=2 | ||
) | ||
for c in "0123456789": | ||
try: | ||
digit_table.add(Paragraph(c, font=ttf)) | ||
except: | ||
digit_table.add(Paragraph("")) | ||
digit_table.set_padding_on_all_cells( | ||
Decimal(2), Decimal(2), Decimal(2), Decimal(2) | ||
) | ||
layout.add(Paragraph("Digits:")) | ||
layout.add(digit_table) | ||
|
||
# return | ||
return pdf | ||
|
||
def test_add_paragraphs_using_jacquard_12(self): | ||
|
||
# set GOOGLE_FONTS_API_KEY | ||
try: | ||
from tests.borb_secrets import populate_os_environ | ||
|
||
populate_os_environ() | ||
except: | ||
pass | ||
|
||
with open(self.get_first_output_file(), "wb") as in_file_handle: | ||
PDF.dumps(in_file_handle, self._write_document_with_font("Jacquard 12")) | ||
self.compare_visually_to_ground_truth(self.get_first_output_file()) | ||
self.check_pdf_using_validator(self.get_first_output_file()) | ||
|
||
def test_add_paragraphs_using_pacifico(self): | ||
|
||
# set GOOGLE_FONTS_API_KEY | ||
try: | ||
from tests.borb_secrets import populate_os_environ | ||
|
||
populate_os_environ() | ||
except: | ||
pass | ||
|
||
with open(self.get_second_output_file(), "wb") as in_file_handle: | ||
PDF.dumps(in_file_handle, self._write_document_with_font("Pacifico")) | ||
self.compare_visually_to_ground_truth(self.get_second_output_file()) | ||
self.check_pdf_using_validator(self.get_second_output_file()) | ||
|
||
def test_add_paragraphs_using_shadows_into_light(self): | ||
|
||
# set GOOGLE_FONTS_API_KEY | ||
try: | ||
from tests.borb_secrets import populate_os_environ | ||
|
||
populate_os_environ() | ||
except: | ||
pass | ||
|
||
with open(self.get_third_output_file(), "wb") as in_file_handle: | ||
PDF.dumps( | ||
in_file_handle, self._write_document_with_font("Shadows Into Light") | ||
) | ||
self.compare_visually_to_ground_truth(self.get_third_output_file()) | ||
self.check_pdf_using_validator(self.get_third_output_file()) |
Binary file removed
BIN
-7.74 KB
.../equation/artifacts_test_add_equation_using_horizontal_alignment/output_002.png
Binary file not shown.
Binary file modified
BIN
+50 Bytes
(100%)
tests/pdf/canvas/layout/image/image/artifacts_test_add_png_image/output_001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+39 Bytes
(100%)
tests/pdf/canvas/layout/image/image/artifacts_test_add_png_image/output_002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+84.1 KB
...f/canvas/layout/image/unsplash/artifacts_test_add_unsplash_image/output_004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.