Merge branch 'master' into ofop
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 2 Mar 2012 13:00:12 +0000 (14:00 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 2 Mar 2012 13:00:12 +0000 (14:00 +0100)
1  2 
librarian/cover.py
librarian/packagers.py
librarian/xslt/book2html.xslt
scripts/book2partner

diff --combined librarian/cover.py
@@@ -34,29 -34,22 +34,29 @@@ class TextBox(object)
          self.height += height
  
      def text(self, text, color='#000', font=None, line_height=20, 
 -             shadow_color=None):
 +             shadow_color=None, shortener=None):
          """Writes some centered text."""
          if shadow_color:
              if not self.shadow_img:
                  self.shadow_img = Image.new('RGBA', self.img.size)
                  self.shadow_draw = ImageDraw.Draw(self.shadow_img)
          while text:
 -            line = text
 -            line_width = self.draw.textsize(line, font=font)[0]
 -            while line_width > self.max_text_width:
 -                parts = line.rsplit(' ', 1)
 -                if len(parts) == 1:
 -                    line_width = self.max_text_width
 -                    break
 -                line = parts[0]
 +            if shortener:
 +                for line in shortener(text):
 +                    if text_draw.textsize(line, font=font)[0] <= self.max_text_width:
 +                        break
 +                text = ''
 +            else:
 +                line = text
                  line_width = self.draw.textsize(line, font=font)[0]
 +                while line_width > self.max_text_width:
 +                    parts = line.rsplit(' ', 1)
 +                    if len(parts) == 1:
 +                        line_width = self.max_text_width
 +                        break
 +                    line = parts[0]
 +                    line_width = self.draw.textsize(line, font=font)[0]
 +
              line = line.strip() + ' '
  
              pos_x = (self.max_width - line_width) / 2
              # go to next line
              text = text[len(line):]
  
 +    @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'…'
 +
      def image(self):
          """Creates the actual Image object."""
          image = Image.new('RGBA', (self.max_width,
@@@ -116,7 -85,6 +116,7 @@@ class Cover(object)
      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
  
          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
              )
          author_font = self.author_font or ImageFont.truetype(
              get_resource('fonts/DejaVuSerif.ttf'), 30)
 +        author_shortener = None if self.author_wrap else TextBox.person_shortener 
          tbox.text(self.pretty_author(), self.author_color, author_font,
 -            self.author_lineskip, self.author_shadow)
 +            self.author_lineskip, self.author_shadow, author_shortener)
          text_img = tbox.image()
          img.paste(text_img, (self.author_margin_left, top), text_img)
          
              )
          title_font = self.author_font or ImageFont.truetype(
              get_resource('fonts/DejaVuSerif.ttf'), 40)
 +        title_shortener = None if self.title_wrap else TextBox.title_shortener 
          tbox.text(self.pretty_title(), self.title_color, title_font,
 -            self.title_lineskip, self.title_shadow)
 +            self.title_lineskip, self.title_shadow, title_shortener)
          text_img = tbox.image()
          img.paste(text_img, (self.title_margin_left, top), text_img)
  
@@@ -232,6 -192,8 +232,8 @@@ class WLCover(Cover)
      bar_width = 35
      background_color = '#444'
      author_color = '#444'
+     default_background = get_resource('res/cover.png')
+     format = 'JPEG'
  
      epochs = {
          u'Starożytność': 0,
              bg_src = urlopen(book_info.cover_url)
              self.background_img = StringIO(bg_src.read())
              bg_src.close()
+         else:
+             self.background_img = self.default_background
  
      def pretty_author(self):
          return self.author.upper()
@@@ -404,42 -368,3 +408,42 @@@ class GandalfCover(Cover)
      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 = 'JPEG'
 +
 +    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
diff --combined librarian/packagers.py
@@@ -63,12 -63,6 +63,12 @@@ class GandalfEpubPackager(EpubPackager)
  class GandalfPdfPackager(PdfPackager):
      cover = cover.GandalfCover
  
 +class ArtaTechEpubPackager(EpubPackager):
 +    cover = cover.ArtaTechCover
 +
 +class ArtaTechPdfPackager(PdfPackager):
 +    cover = cover.ArtaTechCover
 +
  class BookotekaEpubPackager(EpubPackager):
      cover = cover.BookotekaCover
  
@@@ -81,7 -75,7 +81,7 @@@ class PrestigioPdfPackager(PdfPackager)
      flags = ('less-advertising',)
  
  
- class VirtualoEpubPackager(Packager):
+ class VirtualoPackager(Packager):
      @staticmethod
      def utf_trunc(text, limit):
          """ truncates text to at most `limit' bytes in utf-8 """
                  cover.VirtualoCover(info).save(os.path.join(outfile_dir, slug+'.jpg'))
                  outfile = os.path.join(outfile_dir, '1.epub')
                  outfile_sample = os.path.join(outfile_dir, '1.sample.epub')
-                 doc.save_output_file(epub.transform(doc),
+                 doc.save_output_file(doc.as_epub(),
                          output_path=outfile)
-                 doc.save_output_file(epub.transform(doc, sample=25), 
+                 doc.save_output_file(doc.as_epub(doc, sample=25), 
+                         output_path=outfile_sample)
+                 outfile = os.path.join(outfile_dir, '1.mobi')
+                 outfile_sample = os.path.join(outfile_dir, '1.sample.mobi')
+                 doc.save_output_file(doc.as_mobi(cover=cover.VirtualoCover),
+                         output_path=outfile)
+                 doc.save_output_file(
+                         doc.as_mobi(doc, cover=cover.VirtualoCover, sample=25), 
                          output_path=outfile_sample)
          except ParseError, e:
              print '%(file)s:%(name)s:%(message)s' % {
      xmlns:dc="http://purl.org/dc/elements/1.1/" >
  
  <xsl:output encoding="utf-8" indent="yes" omit-xml-declaration = "yes" version="2.0" />
+ <xsl:strip-space  elements="opowiadanie powiesc dramat_wierszowany_l dramat_wierszowany_lp dramat_wspolczesny liryka_l liryka_lp wywiad"/>
  <xsl:template match="utwor">
      <xsl:choose>
          <xsl:when test="@full-page">
              <html>
              <head>
 -                <title>Książka z serwisu WolneLektury.pl</title>
 +                <title><xsl:apply-templates mode="inline" select="//nazwa_utworu" /></title>
                  <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
              </head>
              <style>
@@@ -45,7 -46,6 +46,7 @@@
  
                  img {
                      border: none;
 +                    max-width: 100%;
                  }
  
  
  
  <!-- Section headers (included in index)-->
  <xsl:template match="naglowek_akt|naglowek_czesc|srodtytul">
+   <xsl:call-template name="section-anchor"/>
      <h2><xsl:apply-templates mode="inline" /></h2>
  </xsl:template>
  
  <xsl:template match="naglowek_scena|naglowek_rozdzial">
+     <xsl:call-template name="section-anchor"/>
      <h3><xsl:apply-templates mode="inline" /></h3>
  </xsl:template>
  
  <xsl:template match="naglowek_osoba|naglowek_podrozdzial">
+       <xsl:call-template name="section-anchor"/>
      <h4><xsl:apply-templates mode="inline" /></h4>
  </xsl:template>
  
  <!-- Other paragraph tags -->
  <xsl:template match="miejsce_czas">
+       <xsl:call-template name="section-anchor"/>
      <p class="place-and-time"><xsl:apply-templates mode="inline" /></p>
  </xsl:template>
  
  <xsl:template match="didaskalia">
+       <xsl:call-template name="section-anchor"/>
      <div class="didaskalia"><xsl:apply-templates mode="inline" /></div>
  </xsl:template>
  
  </xsl:template>
  
  <xsl:template match="akap|akap_dialog|akap_cd">
-     <p class="paragraph"><xsl:apply-templates mode="inline" /></p>
+     <p class="paragraph">
+       <xsl:call-template name="section-anchor"/>
+       <xsl:apply-templates mode="inline" />
+     </p>
  </xsl:template>
  
  <xsl:template match="strofa">
      <div class="stanza">
+       <xsl:call-template name="section-anchor"/>
          <xsl:choose>
              <xsl:when test="count(br) > 0">
                  <xsl:call-template name="verse">
      <hr class="spacer-line" />
  </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>
 +        <xsl:attribute name="alt">
 +          <xsl:apply-templates mode="inline" />
 +        </xsl:attribute>
 +        <xsl:attribute name="title">
 +          <xsl:apply-templates mode="inline" />
 +        </xsl:attribute>
 +      </img>
 +    </div>
 +</xsl:template>
 +
  
  <!-- ================ -->
  <!-- = SPECIAL TAGS = -->
      <xsl:value-of select="wl:substitute_entities(.)" />
  </xsl:template>
  
+ <!-- ========= -->
+ <!-- = utils = -->
+ <!-- ========= -->
+ <xsl:template name="section-anchor">
+   <!-- 
+        this formula works as follows:
+        - get all ancestors including self
+        - choose the header (third one from root): utwor/book-type/header
+        - get all preceding siblings
+        - count them
+        - create an <a name="sec123"/> tag.
+   -->
+         <a name="{concat('sec', count(ancestor-or-self::*[last()-2]/preceding-sibling::*) + 1)}" />
+ </xsl:template>
  
- </xsl:stylesheet>
+ </xsl:stylesheet>
diff --combined scripts/book2partner
@@@ -26,10 -26,6 +26,10 @@@ if __name__ == '__main__'
                        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)
+         packagers.VirtualoPackager.prepare(input_filenames, options.output_dir, options.verbose)
      if options.prestigio:
          packagers.PrestigioEpubPackager.prepare(input_filenames, options.output_dir, options.verbose)
      if options.prestigio_pdf: