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
19 background_color = '#000'
26 sticker_padding_x = 30
27 sticker_padding_y = 50
34 'rgb': (0xc3, 0x27, 0x21),
38 'rgb': (0xa0, 0xbf, 0x38),
42 'rgb': (0xed, 0xc0, 0x16),
46 'rgb': (0x47, 0x66, 0x75),
50 for c in color_schemes:
51 c['luminance'] = luminance(c['rgb'])
52 cim = PIL.Image.new('RGB', (1, 1))
53 cim.putpixel((0, 0), c['rgb'])
55 c['hsv'] = cim.getpixel((0, 0))
58 def set_size(self, final_width, final_height):
59 if final_width is None:
60 self.m = Metric(self, 1)
62 if final_width > self.width:
63 self.m = Metric(self, final_width / self.width)
65 self.m = Metric(self, 1)
66 self.scale_after = final_width / self.width
68 if final_height is not None:
69 self.height = round(final_height / self.scale_after / self.m._scale)
71 self.square_variant = self.height / self.width < 250 / 210
73 marquise_square_small = int(self.width / 2) - 300
74 marquise_square_big = int(self.width / 2) - 100
75 marquise_a4_small = 2970 - self.width
76 marquise_a4_big = marquise_a4_small + 100
78 self.marquise_small = int(round(marquise_square_small + (marquise_a4_small - marquise_square_small) * (self.height - self.width) / (2970 - 2100)))
79 self.marquise_big = int(round(marquise_square_big + (marquise_a4_big - marquise_square_big) * (self.height - self.width) / (2970 - 2100)))
80 self.marquise_xl = self.marquise_big + 200
82 if self.marquise_small > self.marquise_big:
83 self.marquise_small = self.marquise_big
85 def set_color_scheme_from(self, img):
86 self.color_scheme = algo_contrast_or_hue(img, self.color_schemes)
87 self.is_very_bright = is_very_bright(img)
90 img = PIL.Image.new('RGB', (self.m.width, self.m.height), self.background_color)
93 bg = Background(self, crop_to_square=False)
97 self.m.width, self.m.height
100 bg = Background(self)
101 if self.square_variant:
103 (self.m.marquise_small, 1),
104 (self.m.marquise_big, 2),
105 (self.m.marquise_big, 3),
106 (self.m.marquise_big, None),
110 (self.m.marquise_small, 2),
111 (self.m.marquise_small, 1),
112 (self.m.marquise_big, 3),
113 (self.m.marquise_xl, 4),
114 (self.m.marquise_xl, None),
117 # Trying all the layout options with decreasing scale.
120 while title_box is None:
121 for marquise_h, lines in layout_options:
122 title_box_height = marquise_h - self.m.title_box_top - self.m.margin
124 title_box = TitleBox(
126 self.m.width - 2 * self.m.margin,
137 self.marquise_height = marquise_h
138 marquise = Marquise(self, self.marquise_height)
142 0, marquise.edge_top,
143 self.m.width, self.m.height - marquise.edge_top
145 self.set_color_scheme_from(
147 0, marquise.edge_top,
148 self.m.width, marquise.edge_top + (
149 self.m.height - marquise.edge_top
155 img, 0, 0, self.m.width
159 marquise.title_box_position[0],
160 marquise.title_box_position[1],
163 AuthorBox(self, self.m.author_width).apply(
164 img, self.m.width - self.m.margin - self.m.author_width, self.m.margin
166 WLLogo(self).apply(img, self.m.margin, self.m.margin, None, self.m.logo_h)
170 LogoSticker(self, self.cover_logo).apply(
172 self.m.width - self.m.margin - self.m.sticker_size,
173 self.m.height - self.m.margin,
174 self.m.sticker_size, self.m.sticker_size, self.m.sticker_padding_x, self.m.sticker_padding_y, self.m.sticker_radius
176 for logo in self.additional_logos:
177 LogoSticker(self, logo).apply(img, 0, 0)
184 class LabelMarquiseCover(MarquiseCover):
191 img = super().image()
192 if not self.predesigned:
196 self.marquise_height - self.label_top,