Implement #5959 (generate default cover on request)

This commit is contained in:
Kovid Goyal 2010-08-04 12:51:18 -06:00
parent cb809e74a8
commit 9aa0fc428d
3 changed files with 113 additions and 4 deletions

View File

@ -142,6 +142,21 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
self.cpixmap = pix
self.cover_data = cover
def generate_cover(self, *args):
from calibre.utils.magick.draw import create_cover_page, TextLine
title = unicode(self.title.text()).strip()
author = unicode(self.authors.text()).strip()
if not title or not author:
return error_dialog(self, _('Specify title and author'),
_('You must specify a title and author before generating '
'a cover'), show=True)
lines = [TextLine(title, 44), TextLine(author, 32)]
self.cover_data = create_cover_page(lines, I('library.png'))
pix = QPixmap()
pix.loadFromData(self.cover_data)
self.cover.setPixmap(pix)
self.cover_changed = True
self.cpixmap = pix
def add_format(self, x):
files = choose_files(self, 'add formats dialog',
@ -425,6 +440,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
self.central_widget.tabBar().setVisible(False)
else:
self.create_custom_column_editors()
self.generate_cover_button.clicked.connect(self.generate_cover)
def create_custom_column_editors(self):
w = self.central_widget.widget(1)

View File

@ -653,6 +653,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="generate_cover_button">
<property name="text">
<string>&amp;Generate cover</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -736,15 +743,17 @@
<tabstop>fetch_metadata_button</tabstop>
<tabstop>add_format_button</tabstop>
<tabstop>remove_format_button</tabstop>
<tabstop>button_set_cover</tabstop>
<tabstop>button_set_metadata</tabstop>
<tabstop>formats</tabstop>
<tabstop>cover_path</tabstop>
<tabstop>cover_button</tabstop>
<tabstop>reset_cover</tabstop>
<tabstop>fetch_cover_button</tabstop>
<tabstop>button_set_cover</tabstop>
<tabstop>formats</tabstop>
<tabstop>button_set_metadata</tabstop>
<tabstop>button_box</tabstop>
<tabstop>generate_cover_button</tabstop>
<tabstop>scrollArea</tabstop>
<tabstop>central_widget</tabstop>
<tabstop>button_box</tabstop>
</tabstops>
<resources>
<include location="../../../../resources/images.qrc"/>

View File

@ -7,6 +7,7 @@ __docformat__ = 'restructuredtext en'
from calibre.utils.magick import Image, DrawingWand, create_canvas
from calibre.constants import __appname__, __version__
def save_cover_data_to(data, path, bgcolor='white', resize_to=None):
'''
@ -77,4 +78,87 @@ def create_text_arc(text, font_size, font=None, bgcolor='white'):
canvas.trim(0)
return canvas
def _get_line(img, dw, tokens, line_width):
line, rest = tokens, []
while True:
m = img.font_metrics(dw, ' '.join(line))
width, height = m.text_width, m.text_height
if width < line_width:
return line, rest
rest = line[-1:] + rest
line = line[:-1]
def annotate_img(img, dw, left, top, rotate, text,
translate_from_top_left=True):
if isinstance(text, unicode):
text = text.encode('utf-8')
if translate_from_top_left:
m = img.font_metrics(dw, text)
img_width, img_height = img.size
left = left - img_width/2. + m.text_width/2.
top = top - img_height/2. + m.text_height/2.
img.annotate(dw, left, top, rotate, text)
def draw_centered_line(img, dw, line, top):
m = img.font_metrics(dw, line)
width, height = m.text_width, m.text_height
img_width = img.size[0]
left = max(int((img_width - width)/2.), 0)
annotate_img(img, dw, left, top, 0, line)
return top + height
def draw_centered_text(img, dw, text, top, margin=10):
img_width = img.size[0]
tokens = text.split(' ')
while tokens:
line, tokens = _get_line(img, dw, tokens, img_width-2*margin)
if not line:
# Could not fit the first token on the line
line = tokens[:1]
tokens = tokens[1:]
bottom = draw_centered_line(img, dw, ' '.join(line), top)
top = bottom
return top
class TextLine(object):
def __init__(self, text, font_size, bottom_margin=30, font_path=None):
self.text, self.font_size, = text, font_size
self.bottom_margin = bottom_margin
self.font_path = font_path
def __repr__(self):
return u'TextLine:%r:%f'%(self.text, self.font_size)
def create_cover_page(top_lines, logo_path, width=590, height=750,
bgcolor='white', output_format='jpg'):
'''
Create the standard calibre cover page and return it as a byte string in
the specified output_format.
'''
canvas = create_canvas(width, height, bgcolor)
bottom = 10
for line in top_lines:
twand = create_text_wand(line.font_size, font_path=line.font_path)
bottom = draw_centered_text(canvas, twand, line.text, bottom)
bottom += line.bottom_margin
bottom -= top_lines[-1].bottom_margin
vanity = create_text_arc(__appname__ + ' ' + __version__, 24,
font=P('fonts/liberation/LiberationMono-Regular.ttf'))
lwidth, lheight = vanity.size
left = int(max(0, (width - lwidth)/2.))
top = height - lheight - 10
canvas.compose(vanity, left, top)
logo = Image()
logo.open(logo_path)
lwidth, lheight = logo.size
left = int(max(0, (width - lwidth)/2.))
top = max(int((height - lheight)/2.), bottom+20)
canvas.compose(logo, left, top)
return canvas.export(output_format)