1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
 
   2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
 
  11     for word in text.split():
 
  13             words[-1] += ' ' + word
 
  16         conj = len(word.lstrip('(').lstrip('[')) == 1
 
  21 def text_with_tracking(draw, tracking, pos, text, fill=None, font=None):
 
  24         # TODO: adjust for kerning?
 
  25         width = font.getlength(c)
 
  26         draw.text((x, y), c, fill=fill, font=font)
 
  30 class DoesNotFit(Exception):
 
  35     def __init__(self, width, height, texts,
 
  36                  font, lines, leading, tracking,
 
  43         self.leading = leading
 
  44         self.tracking = tracking
 
  45         self.align_h = align_h
 
  46         self.align_v = align_v
 
  48         self.margin_top = self.font.getbbox('l')[1]
 
  50         self.glue = self.get_length(' ')
 
  53             (self.get_length(word), word)
 
  54             for word in self.texts
 
  57         self.grouping = self.find_grouping(groups, self.lines, self.glue)
 
  58         if self.grouping is None:
 
  61     def get_length(self, text):
 
  62         return self.font.getlength(text) + self.tracking * len(text)
 
  64     def as_pil_image(self, color):
 
  65         img = PIL.Image.new('RGBA', (self.width, self.height + 2 * self.margin_top))
 
  66         draw = PIL.ImageDraw.ImageDraw(img)
 
  68         font_letter_height = self.font.getmetrics()[0] - self.margin_top
 
  70         y = self.align_v * (self.height - ((self.lines - 1) * self.leading + font_letter_height))
 
  71         for group in self.grouping:
 
  72             x = (self.width - group[0] + self.tracking) * self.align_h
 
  73             self.align_h *  - group[0] / 2
 
  76                     draw, self.tracking, (x, y),
 
  77                     w, fill=color, font=self.font
 
  84     def find_grouping(self, groups, ngroups, glue):
 
  90         mean = sum(g[0] for g in groups) + (len(groups) - ngroups) * glue
 
  91         if mean > self.width * ngroups:
 
  94         for grouping in self.all_groupings(groups, ngroups, glue):
 
  95             if max(g[0] for g in grouping) > self.width:
 
  97             var = sum((g[0] - mean) ** 2 for g in grouping)
 
  98             if best is None or best_var > var:
 
  99                 best, best_var = grouping, var
 
 103     def all_groupings(self, groups, ngroups, glue):
 
 106                 yield [(groups[0][0], groups)]
 
 108         next_groups = groups[1:]
 
 109         for grouping in self.all_groupings(next_groups, ngroups, glue):
 
 112                     groups[0][0] + glue + grouping[0][0],
 
 113                     [groups[0]] + grouping[0][1]
 
 117             for grouping in self.all_groupings(next_groups, ngroups - 1, glue):
 
 119                     (groups[0][0], [groups[0]])