background_color = '#fff'
background_img = None
+ author_align = 'c'
author_top = 100
author_margin_left = 20
author_margin_right = 20
author_color = '#000'
author_shadow = None
author_font = None
+ author_wrap = True
+ title_align = 'c'
title_top = 100
title_margin_left = 20
title_margin_right = 20
title_color = '#000'
title_shadow = None
title_font = None
+ title_wrap = True
logo_bottom = None
logo_width = None
'PNG': 'image/png',
}
+ @staticmethod
+ def person_shortener(text):
+ yield text
+ chunks = text.split()
+ n_chunks = len(chunks)
+ # make initials from given names, starting from last
+ for i in range(n_chunks - 2, -1, -1):
+ chunks[i] = chunks[i][0] + '.'
+ yield " ".join(chunks)
+ # remove given names initials, starting from last
+ while len(chunks) > 2:
+ del chunks[1]
+ yield " ".join(chunks)
+
+ @staticmethod
+ def title_shortener(text):
+ yield text
+ chunks = text.split()
+ n_chunks = len(chunks)
+ # remove words, starting from last one
+ while len(chunks) > 1:
+ del chunks[-1]
+ yield " ".join(chunks) + u'…'
@staticmethod
- def draw_centered_text(text, img, font, margin_left, width, pos_y, lineskip, color, shadow_color):
+ def draw_text(text, img, font, align, shortener, margin_left, width, pos_y, lineskip, color, shadow_color):
if shadow_color:
shadow_img = Image.new('RGBA', img.size)
shadow_draw = ImageDraw.Draw(shadow_img)
text_img = Image.new('RGBA', img.size)
text_draw = ImageDraw.Draw(text_img)
while text:
- line = text
- while text_draw.textsize(line, font=font)[0] > width:
- try:
- line, ext = line.rsplit(' ', 1)
- except:
- break
- pos_x = margin_left + (width - text_draw.textsize(line, font=font)[0]) / 2
+ if shortener:
+ for line in shortener(text):
+ if text_draw.textsize(line, font=font)[0] <= width:
+ break
+ text = ''
+ else:
+ line = text
+ while text_draw.textsize(line, font=font)[0] > width:
+ try:
+ line, ext = line.rsplit(' ', 1)
+ except:
+ break
+ text = text[len(line)+1:]
+ pos_x = margin_left
+ if align == 'c':
+ pos_x += (width - text_draw.textsize(line, font=font)[0]) / 2
+ elif align == 'r':
+ pos_x += (width - text_draw.textsize(line, font=font)[0])
if shadow_color:
shadow_draw.text((pos_x + 3, pos_y + 3), line, font=font, fill=shadow_color)
text_draw.text((pos_x, pos_y), line, font=font, fill=color)
pos_y += lineskip
- text = text[len(line)+1:]
if shadow_color:
shadow_img = shadow_img.filter(ImageFilter.BLUR)
img.paste(shadow_img, None, shadow_img)
if self.background_img:
background = Image.open(self.background_img)
- img.paste(background, None, background)
+ try:
+ img.paste(background, None, background)
+ except ValueError, e:
+ img.paste(background)
del background
# WL logo
img.paste(logo, ((self.width - self.logo_width) / 2, img.size[1] - logo.size[1] - self.logo_bottom))
author_font = self.author_font or ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 30)
- title_y = self.draw_centered_text(self.pretty_author(), img, author_font,
+ author_shortener = None if self.author_wrap else self.person_shortener
+ title_y = self.draw_text(self.pretty_author(), img, author_font, self.author_align, author_shortener,
self.author_margin_left, self.width - self.author_margin_left - self.author_margin_right, self.author_top,
self.author_lineskip, self.author_color, self.author_shadow) + self.title_top
+ title_shortener = None if self.title_wrap else self.title_shortener
title_font = self.title_font or ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 40)
- self.draw_centered_text(self.pretty_title(), img, title_font,
+ self.draw_text(self.pretty_title(), img, title_font, self.title_align, title_shortener,
self.title_margin_left, self.width - self.title_margin_left - self.title_margin_right, title_y,
self.title_lineskip, self.title_color, self.title_shadow)
logo_bottom = 25
logo_width = 250
format = 'PNG'
+
+
+class ArtaTechCover(Cover):
+ width = 600
+ height = 800
+ background_img = get_resource('res/cover-arta-tech.jpg')
+ author_top = 132
+ author_margin_left = 235
+ author_margin_right = 23
+ author_align = 'r'
+ author_font = ImageFont.truetype(get_resource('fonts/DroidSans.ttf'), 32)
+ author_color = '#555555'
+ author_wrap = False
+ title_top = 17
+ title_margin_right = 21
+ title_margin_left = 60
+ title_align = 'r'
+ title_font = ImageFont.truetype(get_resource('fonts/EBGaramond-Regular.ttf'), 42)
+ title_color = '#222222'
+ title_wrap = False
+ format = 'PNG'
+
+ def pretty_author(self):
+ return self.author.upper()
+
+
+def ImageCover(img):
+ """ a class factory for simple image covers """
+ img = Image.open(img)
+
+ class ImgCover(Cover):
+ def image(self):
+ return img
+
+ @property
+ def format(self):
+ return self.image().format
+
+ return ImgCover
#
from __future__ import with_statement
+from copy import deepcopy
import os
import os.path
import subprocess
from librarian import XMLNamespace, RDFNS, DCNS, WLNS, NCXNS, OPFNS, XHTMLNS, NoDublinCore
from librarian.dcparser import BookInfo
+from librarian.cover import ImageCover
from librarian import functions, get_resource
make_dir: writes output to <output_dir>/<author>/<slug>.epub instead of <output_dir>/<slug>.epub
sample=n: generate sample e-book (with at least n paragraphs)
cover: a cover.Cover object
- flags: less-advertising,
+ flags: less-advertising, images, not-wl
"""
def transform_file(input_xml, chunk_counter=1, first=True, sample=None):
else:
output_file = open(os.path.join(output_dir, os.path.splitext(os.path.basename(file_path))[0] + '.epub'), 'w')
+ opf = xslt(metadata, get_resource('epub/xsltContent.xsl'))
+ manifest = opf.find('.//' + OPFNS('manifest'))
+ spine = opf.find('.//' + OPFNS('spine'))
+
zip = zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED)
# write static elements
'media-type="application/oebps-package+xml" />' \
'</rootfiles></container>')
zip.write(get_resource('epub/style.css'), os.path.join('OPS', 'style.css'))
- zip.write(get_resource('res/wl-logo-small.png'), os.path.join('OPS', 'logo_wolnelektury.png'))
-
- opf = xslt(metadata, get_resource('epub/xsltContent.xsl'))
- manifest = opf.find('.//' + OPFNS('manifest'))
- spine = opf.find('.//' + OPFNS('spine'))
+ if not flags or 'not-wl' not in flags:
+ manifest.append(etree.fromstring(
+ '<item id="logo_wolnelektury" href="logo_wolnelektury.png" media-type="image/png" />'))
+ zip.write(get_resource('res/wl-logo-small.png'), os.path.join('OPS', 'logo_wolnelektury.png'))
if cover:
cover_file = StringIO()
opf.getroot()[0].append(etree.fromstring('<meta name="cover" content="cover-image"/>'))
opf.getroot().append(etree.fromstring('<guide><reference href="cover.html" type="cover" title="Okładka"/></guide>'))
+ if flags and 'images' in flags:
+ for ilustr in input_xml.findall('//ilustr'):
+ src = ilustr.get('src')
+ mime = ImageCover(src)().mime_type()
+ zip.write(src, os.path.join('OPS', src))
+ manifest.append(etree.fromstring(
+ '<item id="%s" href="%s" media-type="%s" />' % (src, src, mime)))
+ # get it up to master
+ after = ilustr
+ while after.getparent().tag not in ['powiesc', 'opowiadanie', 'liryka_l', 'liryka_lp', 'dramat_wierszowany_l', 'dramat_wierszowany_lp', 'dramat_wspolczesny']:
+ after = after.getparent()
+ if not(after is ilustr):
+ moved = deepcopy(ilustr)
+ ilustr.tag = 'extra'
+ ilustr.text = None
+ moved.tail = None
+ after.addnext(moved)
+ else:
+ for ilustr in input_xml.findall('//ilustr'):
+ ilustr.tag = 'extra'
annotations = etree.Element('annotations')
'<item id="last" href="last.html" media-type="application/xhtml+xml" />'))
spine.append(etree.fromstring(
'<itemref idref="last" />'))
- html_tree = xslt(input_xml, get_resource('epub/xsltLast.xsl'))
+ stopka = input_xml.find('//stopka')
+ if stopka is not None:
+ stopka.tag = 'stopka_'
+ replace_by_verse(stopka)
+ html_tree = xslt(stopka, get_resource('epub/xsltScheme.xsl'))
+ else:
+ html_tree = xslt(input_xml, get_resource('epub/xsltLast.xsl'))
chars.update(used_chars(html_tree.getroot()))
zip.writestr('OPS/last.html', etree.tostring(
html_tree, method="html", pretty_print=True))
#book-text
{
- margin: 2em;
+ /*margin: 2em;*/
+ margin: 5px;
/*margin-right: 9em;*/
}
p.footer {
margin-top: 2em;
}
+
+.ilustr {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.ilustr img {
+ max-width: 100%;
+}
<item id="toc" href="toc.ncx" media-type="application/x-dtbncx+xml" />
<item id="style" href="style.css" media-type="text/css" />
<item id="titlePage" href="title.html" media-type="application/xhtml+xml" />
- <item id="logo_wolnelektury" href="logo_wolnelektury.png" media-type="image/png" />
<item id="DejaVuSerif.ttf" href="DejaVuSerif.ttf" media-type="font/ttf" />
<item id="DejaVuSerif-Bold.ttf" href="DejaVuSerif-Bold.ttf" media-type="font/ttf" />
<item id="DejaVuSerif-BoldItalic.ttf" href="DejaVuSerif-BoldItalic.ttf" media-type="font/ttf" />
</dc:title>
</xsl:template>
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>
<hr class="spacer-line" xmlns="http://www.w3.org/1999/xhtml"></hr>
</xsl:template>
+ <xsl:template match="ilustr">
+ <div xmlns="http://www.w3.org/1999/xhtml" class="ilustr">
+ <img xmlns="http://www.w3.org/1999/xhtml" alt="ilustracja">
+ <xsl:attribute name="src">
+ <xsl:value-of select="@src" />
+ </xsl:attribute>
+ </img>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="stopka" />
+
<!--===========================================================-->
<!-- Tagi SPECJALNE -->
<!--===========================================================-->
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:template>
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>
<xsl:call-template name="translators" />
+ <xsl:if test="not(utwor/@not-wl)">
<xsl:if test="not(utwor/@less-advertising)">
<p class="info">
<a>
<p class="footer info">
<a href="http://www.wolnelektury.pl/"><img src="logo_wolnelektury.png" alt="WolneLektury.pl" /></a>
</p>
+ </xsl:if>
+ <!--xsl:if test="utwor/@not-wl">
+ <p class="info">
+ Konwersja wykonana przez<a href="http://www.nowoczesnapolska.org.pl/"> fundację Nowoczesna Polska</a>.
+ </p>
+ </xsl:if-->
</div>
</body>
</html>
<xsl:template match="motyw" />
-</xsl:stylesheet>
\ No newline at end of file
+</xsl:stylesheet>
class GandalfPdfPackager(PdfPackager):
cover = cover.GandalfCover
+class ArtaTechEpubPackager(EpubPackager):
+ cover = cover.ArtaTechCover
+
+class ArtaTechPdfPackager(PdfPackager):
+ cover = cover.ArtaTechCover
+
class BookotekaEpubPackager(EpubPackager):
cover = cover.BookotekaCover
import optparse
from librarian import epub, DirDocProvider, ParseError
+from librarian.cover import ImageCover
if __name__ == '__main__':
help='specifies the output file')
parser.add_option('-O', '--output-dir', dest='output_dir', metavar='DIR',
help='specifies the directory for output')
+ parser.add_option('-i', '--with-images', action='store_true', dest='images', default=False,
+ help='add images with <ilustr src="..."/>')
+ parser.add_option('-A', '--less-advertising', action='store_true', dest='less_advertising', default=False,
+ help='less advertising, for commercial purposes')
+ parser.add_option('-W', '--not-wl', action='store_true', dest='not_wl', default=False,
+ help='not a WolneLektury book')
+ parser.add_option('-c', '--cover', dest='cover', metavar='FILE',
+ help='specifies the cover file')
options, input_filenames = parser.parse_args()
else:
output_dir = path
- epub.transform(provider, file_path=main_input, output_dir=output_dir, output_file=output_file, make_dir=options.make_dir)
+ cover = None
+ if options.cover:
+ cover = ImageCover(options.cover)
+
+ flags = []
+ if options.images:
+ flags.append('images')
+ if options.less_advertising:
+ flags.append('less-advertising')
+ if options.not_wl:
+ flags.append('not-wl')
+
+ epub.transform(provider, file_path=main_input, output_dir=output_dir, output_file=output_file, make_dir=options.make_dir,
+ cover=cover, flags=flags)
except ParseError, e:
print '%(file)s:%(name)s:%(message)s' % {
'file': main_input,
help='prepare EPUB files for Gandalf')
parser.add_option('--gandalf-pdf', action='store_true', dest='gandalf_pdf', default=False,
help='prepare PDF files for Gandalf')
+ parser.add_option('--artatech', action='store_true', dest='artatech', default=False,
+ help='prepare EPUB files for Arta-Tech')
+ parser.add_option('--artatech-pdf', action='store_true', dest='artatech_pdf', default=False,
+ help='prepare PDF files for Arta-Tech')
parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False,
help='prepare files for Virtualo API')
parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False,
packagers.GandalfEpubPackager.prepare(input_filenames, options.output_dir, options.verbose)
if options.gandalf_pdf:
packagers.GandalfPdfPackager.prepare(input_filenames, options.output_dir, options.verbose)
+ if options.artatech:
+ packagers.ArtaTechEpubPackager.prepare(input_filenames, options.output_dir, options.verbose)
+ if options.artatech_pdf:
+ packagers.ArtaTechPdfPackager.prepare(input_filenames, options.output_dir, options.verbose)
if options.virtualo:
packagers.VirtualoEpubPackager.prepare(input_filenames, options.output_dir, options.verbose)
if options.prestigio: