5fa3528bf9d422e9f962f76de99d7e4c90e680a1
[librarian.git] / src / librarian / covers / widgets / author.py
1 import PIL.ImageFont
2 from librarian import get_resource
3 from librarian.cover import Metric
4 from ..utils.textbox import TextBox, DoesNotFit, split_words
5 from .base import Widget
6
7
8 class AuthorBox(Widget):
9     font_size = 75
10     leading = 92
11
12     def __init__(self, cover, width):
13         self.width = width
14         self.m = Metric(self, cover.m._scale)
15         super().__init__(cover)
16
17     def setup(self):
18         author_font = PIL.ImageFont.truetype(
19             get_resource('fonts/SourceSans3VF-Roman.ttf'),
20             self.m.font_size,
21             layout_engine=PIL.ImageFont.LAYOUT_BASIC
22         )
23         author_font.set_variation_by_axes([600])
24
25         translator_font = PIL.ImageFont.truetype(
26             get_resource('fonts/SourceSans3VF-Roman.ttf'),
27             self.m.font_size,
28             layout_engine=PIL.ImageFont.LAYOUT_BASIC
29         )
30         translator_font.set_variation_by_axes([400])
31
32         authors = [a.readable() for a in self.cover.book_info.authors]
33         translators = [a.readable() for a in self.cover.book_info.translators]
34
35         if authors and translators:
36             # Try with two boxes.
37
38             authors_shortened = False
39             author_box = None
40             while author_box is None:
41                 author_str = ', '.join(authors)
42                 if authors_shortened:
43                     # translate!
44                     author_str += ' i in.'
45                 try:
46                     author_box = TextBox(
47                         self.width,
48                         self.m.leading * 2,
49                         [author_str],
50                         author_font,
51                         1,
52                         self.m.leading,
53                         0,
54                         1, 0
55                     )
56                 except DoesNotFit:
57                     authors.pop()
58                     authors_shortened = True
59
60             translators_shortened = False
61             translator_box = None
62             while translator_box is None:
63                 translator_str = '(tłum. ' + ', '.join(translators)
64                 if translators_shortened:
65                     translator_str += ' i in.'
66                 translator_str += ')'
67                 try:
68                     translator_box = TextBox(
69                         self.width,
70                         self.m.leading * 2,
71                         [translator_str],
72                         translator_font,
73                         1,
74                         self.m.leading,
75                         0,
76                         1, 0
77                     )
78                 except DoesNotFit:
79                     translators.pop()
80                     translators_shortened = True
81
82             self.textboxes = [
83                 author_box,
84                 translator_box
85             ]
86
87         elif authors:
88             author_box = None
89             shortened = False
90             while author_box is None:
91                 if not shortened and len(authors) == 2:
92                     parts = authors
93                 elif len(authors) > 2:
94                     parts = [author + ',' for author in authors[:-1]] + [authors[-1]]
95                     if shortened:
96                         parts.append('i in.')
97                 else:
98                     parts = split_words(authors[0])
99                     if shortened:
100                         parts.append('i in.')
101
102                 try:
103                     if len(parts) > 1:
104                         # Author in two lines.
105                         author_box = TextBox(
106                             self.width,
107                             self.m.leading * 2,
108                             parts,
109                             author_font,
110                             2,
111                             self.m.leading,
112                             0,
113                             1, 0
114                         )
115                     else:
116                         # author in one line.
117                         author_box = TextBox(
118                             self.width,
119                             self.m.leading * 2,
120                             parts,
121                             author_font,
122                             1,
123                             self.m.leading,
124                             0,
125                             1, 0
126                         )
127                 except DoesNotFit:
128                     authors.pop()
129                     shortened = True
130
131             self.textboxes = [author_box]
132
133         self.margin_top = self.textboxes[0].margin_top
134
135     def build(self, w, h):
136         img = PIL.Image.new('RGBA', (self.width, self.m.leading * 2))
137         offset = 0
138         for i, tb in enumerate(self.textboxes):
139             sub_img = tb.as_pil_image(self.cover.color_scheme['text'])
140             img.paste(sub_img, (0, self.m.leading * i), sub_img)
141         
142         return img