1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
5 from librarian.cover import Cover, Metric
6 from .utils.color import algo_contrast_or_hue, luminance, is_very_bright
7 from .utils.textbox import DoesNotFit
8 from .widgets.author import AuthorBox
9 from .widgets.background import Background
10 from .widgets.image import WLLogo, Label, LogoSticker
11 from .widgets.marquise import Marquise
12 from .widgets.title import TitleBox
15 class MarquiseCover(Cover):
17 square_variant = False
25 sticker_padding_x = 30
26 sticker_padding_y = 50
33 'rgb': (0xc3, 0x27, 0x21),
37 'rgb': (0xa0, 0xbf, 0x38),
41 'rgb': (0xed, 0xc0, 0x16),
45 'rgb': (0x47, 0x66, 0x75),
49 for c in color_schemes:
50 c['luminance'] = luminance(c['rgb'])
51 cim = PIL.Image.new('RGB', (1, 1))
52 cim.putpixel((0, 0), c['rgb'])
54 c['hsv'] = cim.getpixel((0, 0))
57 def set_size(self, final_width, final_height):
58 if final_width is None:
59 self.m = Metric(self, 1)
61 if final_width > self.width:
62 self.m = Metric(self, final_width / self.width)
64 self.m = Metric(self, 1)
65 self.scale_after = final_width / self.width
67 if final_height is not None:
68 self.height = round(final_height / self.scale_after / self.m._scale)
70 self.square_variant = self.height / self.width < 250 / 210
72 marquise_square_small = int(self.width / 2) - 300
73 marquise_square_big = int(self.width / 2) - 100
74 marquise_a4_small = 2970 - self.width
75 marquise_a4_big = marquise_a4_small + 100
77 self.marquise_small = int(round(marquise_square_small + (marquise_a4_small - marquise_square_small) * (self.height - self.width) / (2970 - 2100)))
78 self.marquise_big = int(round(marquise_square_big + (marquise_a4_big - marquise_square_big) * (self.height - self.width) / (2970 - 2100)))
79 self.marquise_xl = self.marquise_big + 200
81 if self.marquise_small > self.marquise_big:
82 self.marquise_small = self.marquise_big
84 def set_color_scheme_from(self, img):
85 self.color_scheme = algo_contrast_or_hue(img, self.color_schemes)
86 self.is_very_bright = is_very_bright(img)
89 img = PIL.Image.new('RGB', (self.m.width, self.m.height), self.background_color)
92 bg = Background(self, crop_to_square=False)
96 self.m.width, self.m.height
100 if self.square_variant:
102 (self.m.marquise_small, 1),
103 (self.m.marquise_big, 2),
104 (self.m.marquise_big, 3),
105 (self.m.marquise_big, None),
109 (self.m.marquise_small, 2),
110 (self.m.marquise_small, 1),
111 (self.m.marquise_big, 3),
112 (self.m.marquise_xl, 4),
113 (self.m.marquise_xl, None),
116 # Trying all the layout options with decreasing scale.
119 while title_box is None:
120 for marquise_h, lines in layout_options:
121 title_box_height = marquise_h - self.m.title_box_top - self.m.margin
123 title_box = TitleBox(
125 self.m.width - 2 * self.m.margin,
136 self.marquise_height = marquise_h
137 marquise = Marquise(self, self.marquise_height)
141 0, marquise.edge_top,
142 self.m.width, self.m.height - marquise.edge_top
144 self.set_color_scheme_from(
146 0, marquise.edge_top,
147 self.m.width, marquise.edge_top + (
148 self.m.height - marquise.edge_top
154 img, 0, 0, self.m.width
158 marquise.title_box_position[0],
159 marquise.title_box_position[1],
162 AuthorBox(self, self.m.author_width).apply(
163 img, self.m.width - self.m.margin - self.m.author_width, self.m.margin
165 WLLogo(self).apply(img, self.m.margin, self.m.margin, None, self.m.logo_h)
169 LogoSticker(self, self.cover_logo).apply(
171 self.m.width - self.m.margin - self.m.sticker_size,
172 self.m.height - self.m.margin,
173 self.m.sticker_size, self.m.sticker_size, self.m.sticker_padding_x, self.m.sticker_padding_y, self.m.sticker_radius
175 for logo in self.additional_logos:
176 LogoSticker(self, logo).apply(img, 0, 0)
183 class LabelMarquiseCover(MarquiseCover):
190 img = super().image()
191 if not self.predesigned:
195 self.marquise_height - self.label_top,