home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1077 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  8.4 KB  |  234 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
  7. import os
  8. import glob
  9. import re
  10. import textwrap
  11. from lxml import etree
  12. from calibre.customize.conversion import InputFormatPlugin
  13.  
  14. class InlineClass(etree.XSLTExtension):
  15.     FMTS = ('italics', 'bold', 'underlined', 'strike-through', 'small-caps')
  16.     
  17.     def __init__(self, log):
  18.         etree.XSLTExtension.__init__(self)
  19.         self.log = log
  20.         self.font_sizes = []
  21.         self.colors = []
  22.  
  23.     
  24.     def execute(self, context, self_node, input_node, output_parent):
  25.         classes = [
  26.             'none']
  27.         for x in self.FMTS:
  28.             if input_node.get(x, None) == 'true':
  29.                 classes.append(x)
  30.                 continue
  31.         
  32.         fs = input_node.get('font-size', False)
  33.         if fs:
  34.             if fs not in self.font_sizes:
  35.                 self.font_sizes.append(fs)
  36.             
  37.             classes.append('fs%d' % self.font_sizes.index(fs))
  38.         
  39.         fc = input_node.get('font-color', False)
  40.         if fc:
  41.             if fc not in self.colors:
  42.                 self.colors.append(fc)
  43.             
  44.             classes.append('col%d' % self.colors.index(fc))
  45.         
  46.         output_parent.text = ' '.join(classes)
  47.  
  48.  
  49.  
  50. class RTFInput(InputFormatPlugin):
  51.     name = 'RTF Input'
  52.     author = 'Kovid Goyal'
  53.     description = 'Convert RTF files to HTML'
  54.     file_types = set([
  55.         'rtf'])
  56.     
  57.     def generate_xml(self, stream):
  58.         ParseRtf = ParseRtf
  59.         import calibre.ebooks.rtf2xml.ParseRtf
  60.         ofile = 'out.xml'
  61.         parser = ParseRtf(in_file = stream, out_file = ofile, convert_symbol = 1, convert_zapf = 1, convert_wingdings = 1, convert_caps = 1, indent = 1, form_lists = 1, headings_to_sections = 1, group_styles = 1, group_borders = 1, empty_paragraphs = 0)
  62.         parser.parse_rtf()
  63.         ans = open('out.xml').read()
  64.         os.remove('out.xml')
  65.         return ans
  66.  
  67.     
  68.     def extract_images(self, picts):
  69.         self.log('Extracting images...')
  70.         count = 0
  71.         raw = open(picts, 'rb').read()
  72.         starts = []
  73.         for match in re.finditer('\\{\\\\pict([^}]+)\\}', raw):
  74.             starts.append(match.start(1))
  75.         
  76.         imap = { }
  77.         for start in starts:
  78.             pos = start
  79.             bc = 1
  80.             while bc > 0:
  81.                 if raw[pos] == '}':
  82.                     bc -= 1
  83.                 elif raw[pos] == '{':
  84.                     bc += 1
  85.                 
  86.                 pos += 1
  87.             pict = raw[start:pos + 1]
  88.             enc = re.sub('[^a-zA-Z0-9]', '', pict)
  89.             if len(enc) % 2 == 1:
  90.                 enc = enc[:-1]
  91.             
  92.             data = enc.decode('hex')
  93.             count += 1
  94.             name = ('%4d' % count).replace(' ', '0') + '.wmf'
  95.             open(name, 'wb').write(data)
  96.             imap[count] = name
  97.         
  98.         return self.convert_images(imap)
  99.  
  100.     
  101.     def convert_images(self, imap):
  102.         for count, val in imap.items():
  103.             
  104.             try:
  105.                 imap[count] = self.convert_image(val)
  106.             continue
  107.             self.log.exception('Failed to convert', val)
  108.             continue
  109.  
  110.         
  111.         return imap
  112.  
  113.     
  114.     def convert_image(self, name):
  115.         Image = Image
  116.         import calibre.utils.magick
  117.         img = Image()
  118.         img.open(name)
  119.         name = name.replace('.wmf', '.jpg')
  120.         img.save(name)
  121.         return name
  122.  
  123.     
  124.     def write_inline_css(self, ic):
  125.         font_size_classes = [ 'span.fs%d { font-size: %spt }' % (i, x) for i, x in enumerate(ic.font_sizes) ]
  126.         color_classes = [ 'span.col%d { color: %s }' % (i, x) for i, x in enumerate(ic.colors) ]
  127.         css = textwrap.dedent('\n        span.none {\n            text-decoration: none; font-weight: normal;\n            font-style: normal; font-variant: normal\n        }\n\n        span.italics { font-style: italic }\n\n        span.bold { font-weight: bold }\n\n        span.small-caps { font-variant: small-caps }\n\n        span.underlined { text-decoration: underline }\n\n        span.strike-through { text-decoration: line-through }\n\n        ')
  128.         css += '\n' + '\n'.join(font_size_classes)
  129.         css += '\n' + '\n'.join(color_classes)
  130.         
  131.         try:
  132.             f = _[3]
  133.             f.write(css)
  134.         finally:
  135.             pass
  136.  
  137.  
  138.     
  139.     def preprocess(self, fname):
  140.         self.log('\tPreprocessing to convert unicode characters')
  141.         
  142.         try:
  143.             data = open(fname, 'rb').read()
  144.             RtfTokenizer = RtfTokenizer
  145.             RtfTokenParser = RtfTokenParser
  146.             import calibre.ebooks.rtf.preprocess
  147.             tokenizer = RtfTokenizer(data)
  148.             tokens = RtfTokenParser(tokenizer.tokens)
  149.             data = tokens.toRTF()
  150.             fname = 'preprocessed.rtf'
  151.             
  152.             try:
  153.                 f = _[1]
  154.                 f.write(data)
  155.             finally:
  156.                 pass
  157.  
  158.         except:
  159.             self.log.exception('Failed to preprocess RTF to convert unicode sequences, ignoring...')
  160.  
  161.         return fname
  162.  
  163.     
  164.     def convert(self, stream, options, file_ext, log, accelerators):
  165.         get_metadata = get_metadata
  166.         import calibre.ebooks.metadata.meta
  167.         OPFCreator = OPFCreator
  168.         import calibre.ebooks.metadata.opf2
  169.         RtfInvalidCodeException = RtfInvalidCodeException
  170.         import calibre.ebooks.rtf2xml.ParseRtf
  171.         self.log = log
  172.         self.log('Converting RTF to XML...')
  173.         fname = self.preprocess(stream.name)
  174.         
  175.         try:
  176.             xml = self.generate_xml(fname)
  177.         except RtfInvalidCodeException:
  178.             e = None
  179.             raise ValueError(_('This RTF file has a feature calibre does not support. Convert it to HTML first and then try it.\n%s') % e)
  180.  
  181.         d = glob.glob(os.path.join('*_rtf_pict_dir', 'picts.rtf'))
  182.         if d:
  183.             imap = { }
  184.             
  185.             try:
  186.                 imap = self.extract_images(d[0])
  187.             self.log.exception('Failed to extract images...')
  188.  
  189.         
  190.         self.log('Parsing XML...')
  191.         parser = etree.XMLParser(recover = True, no_network = True)
  192.         doc = etree.fromstring(xml, parser = parser)
  193.         for pict in doc.xpath('//rtf:pict[@num]', namespaces = {
  194.             'rtf': 'http://rtf2xml.sourceforge.net/' }):
  195.             num = int(pict.get('num'))
  196.             name = imap.get(num, None)
  197.             if name is not None:
  198.                 pict.set('num', name)
  199.                 continue
  200.         
  201.         self.log('Converting XML to HTML...')
  202.         inline_class = InlineClass(self.log)
  203.         styledoc = etree.fromstring(P('templates/rtf.xsl', data = True))
  204.         extensions = {
  205.             ('calibre', 'inline-class'): inline_class }
  206.         transform = etree.XSLT(styledoc, extensions = extensions)
  207.         result = transform(doc)
  208.         html = 'index.xhtml'
  209.         
  210.         try:
  211.             f = _[1]
  212.             res = transform.tostring(result)
  213.             res = res[:100].replace('xmlns:html', 'xmlns') + res[100:]
  214.             f.write(res)
  215.         finally:
  216.             pass
  217.  
  218.         self.write_inline_css(inline_class)
  219.         stream.seek(0)
  220.         mi = get_metadata(stream, 'rtf')
  221.         if not mi.authors:
  222.             mi.authors = [
  223.                 _('Unknown')]
  224.         
  225.         opf = OPFCreator(os.getcwd(), mi)
  226.         opf.create_manifest([
  227.             ('index.xhtml', None)])
  228.         opf.create_spine([
  229.             'index.xhtml'])
  230.         opf.render(open('metadata.opf', 'wb'))
  231.         return os.path.abspath('metadata.opf')
  232.  
  233.  
  234.