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