4060999402d33362a0ad93e30cd10432435e08f7
[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         self.textboxes = []
35
36         if authors and translators:
37             # Try with two boxes.
38
39             authors_shortened = False
40             author_box = None
41             while author_box is None:
42                 author_str = ', '.join(authors)
43                 if authors_shortened:
44                     # translate!
45                     author_str += ' i in.'
46                 try:
47                     author_box = TextBox(
48                         self.width,
49                         self.m.leading * 2,
50                         [author_str],
51                         author_font,
52                         1,
53                         self.m.leading,
54                         0,
55                         1, 0
56                     )
57                 except DoesNotFit:
58                     authors.pop()
59                     authors_shortened = True
60
61             translators_shortened = False
62             translator_box = None
63             while translator_box is None:
64                 translator_str = '(tłum. ' + ', '.join(translators)
65                 if translators_shortened:
66                     translator_str += ' i in.'
67                 translator_str += ')'
68                 try:
69                     translator_box = TextBox(
70                         self.width,
71                         self.m.leading * 2,
72                         [translator_str],
73                         translator_font,
74                         1,
75                         self.m.leading,
76                         0,
77                         1, 0
78                     )
79                 except DoesNotFit:
80                     translators.pop()
81                     translators_shortened = True
82
83             self.textboxes = [
84                 author_box,
85                 translator_box
86             ]
87
88         elif authors:
89             author_box = None
90             shortened = False
91             while author_box is None:
92                 if not shortened and len(authors) == 2:
93                     parts = authors
94                 elif len(authors) > 2:
95                     parts = [author + ',' for author in authors[:-1]] + [authors[-1]]
96                     if shortened:
97                         parts.append('i in.')
98                 else:
99                     parts = split_words(authors[0])
100                     if shortened:
101                         parts.append('i in.')
102
103                 try:
104                     if len(parts) > 1:
105                         # Author in two lines.
106                         author_box = TextBox(
107                             self.width,
108                             self.m.leading * 2,
109                             parts,
110                             author_font,
111                             2,
112                             self.m.leading,
113                             0,
114                             1, 0
115                         )
116                     else:
117                         # author in one line.
118                         author_box = TextBox(
119                             self.width,
120                             self.m.leading * 2,
121                             parts,
122                             author_font,
123                             1,
124                             self.m.leading,
125                             0,
126                             1, 0
127                         )
128                 except DoesNotFit:
129                     authors.pop()
130                     shortened = True
131
132             self.textboxes = [author_box]
133
134         if self.textboxes:
135             self.margin_top = self.textboxes[0].margin_top
136
137     def build(self, w, h):
138         img = PIL.Image.new('RGBA', (self.width, self.m.leading * 2))
139         offset = 0
140         for i, tb in enumerate(self.textboxes):
141             sub_img = tb.as_pil_image(self.cover.color_scheme['text'])
142             img.paste(sub_img, (0, self.m.leading * i), sub_img)
143         
144         return img