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,