home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_922 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  15.9 KB  |  488 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__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
  7. __docformat__ = 'restructuredtext en'
  8. import os
  9. import textwrap
  10. from copy import deepcopy
  11. from lxml import etree
  12. from calibre.customize.conversion import InputFormatPlugin
  13. from calibre import guess_type
  14.  
  15. class Canvas(etree.XSLTExtension):
  16.     
  17.     def __init__(self, doc, styles, text_block, log):
  18.         self.doc = doc
  19.         self.styles = styles
  20.         self.text_block = text_block
  21.         self.log = log
  22.         self.processed = set([])
  23.  
  24.     
  25.     def execute(self, context, self_node, input_node, output_parent):
  26.         cid = input_node.get('objid', None)
  27.         if cid is None or cid in self.processed:
  28.             return None
  29.         self.processed.add(cid)
  30.         input_node = self.doc.xpath('//Canvas[@objid="%s"]' % cid)[0]
  31.         objects = list(self.get_objects(input_node))
  32.         if len(objects) == 1 and objects[0][0].tag == 'ImageBlock':
  33.             self.image_page(input_node, objects[0][0], output_parent)
  34.         else:
  35.             canvases = [
  36.                 input_node]
  37.             for x in input_node.itersiblings():
  38.                 if x.tag == 'Canvas':
  39.                     oid = x.get('objid', None)
  40.                     if oid is not None:
  41.                         canvases.append(x)
  42.                         self.processed.add(oid)
  43.                     
  44.                 oid is not None
  45.             
  46.             table = etree.Element('table')
  47.             table.text = '\n\t'
  48.             for canvas in canvases:
  49.                 oid = canvas.get('objid')
  50.                 tr = table.makeelement('tr')
  51.                 tr.set('id', oid)
  52.                 tr.tail = '\n\t'
  53.                 table.append(tr)
  54.                 for obj, x, y in self.get_objects(canvas):
  55.                     if obj.tag != 'TextBlock':
  56.                         self.log.warn(obj.tag, 'elements in Canvas not supported')
  57.                         continue
  58.                     
  59.                     td = table.makeelement('td')
  60.                     self.text_block.render_block(obj, td)
  61.                     tr.append(td)
  62.                 
  63.             
  64.             output_parent.append(table)
  65.  
  66.     
  67.     def image_page(self, input_node, block, output_parent):
  68.         div = etree.Element('div')
  69.         div.set('id', input_node.get('objid', 'scuzzy'))
  70.         div.set('class', 'image_page')
  71.         width = self.styles.to_num(block.get('xsize', None))
  72.         height = self.styles.to_num(block.get('ysize', None))
  73.         img = div.makeelement('img')
  74.         if width is not None:
  75.             img.set('width', str(int(width)))
  76.         
  77.         if height is not None:
  78.             img.set('height', str(int(height)))
  79.         
  80.         ref = block.get('refstream', None)
  81.         if ref is not None:
  82.             imstr = self.doc.xpath('//ImageStream[@objid="%s"]' % ref)
  83.             if imstr:
  84.                 src = imstr[0].get('file', None)
  85.                 if src:
  86.                     img.set('src', src)
  87.                 
  88.             
  89.         
  90.         div.append(img)
  91.         output_parent.append(div)
  92.  
  93.     
  94.     def get_objects(self, node):
  95.         for x in node.xpath('descendant::PutObj[@refobj and @x1 and @y1]'):
  96.             objs = node.xpath('//*[@objid="%s"]' % x.get('refobj'))
  97.             (x, y) = map(self.styles.to_num, (x.get('x1'), x.get('y1')))
  98.             if objs and x is not None and y is not None:
  99.                 yield (objs[0], int(x), int(y))
  100.                 continue
  101.         
  102.  
  103.  
  104.  
  105. class MediaType(etree.XSLTExtension):
  106.     
  107.     def execute(self, context, self_node, input_node, output_parent):
  108.         name = input_node.get('file', None)
  109.         typ = guess_type(name)[0]
  110.         if not typ:
  111.             typ = 'application/octet-stream'
  112.         
  113.         output_parent.text = typ
  114.  
  115.  
  116.  
  117. class ImageBlock(etree.XSLTExtension):
  118.     
  119.     def __init__(self, canvas):
  120.         etree.XSLTExtension.__init__(self)
  121.         self.canvas = canvas
  122.  
  123.     
  124.     def execute(self, context, self_node, input_node, output_parent):
  125.         self.canvas.image_page(input_node, input_node, output_parent)
  126.  
  127.  
  128.  
  129. class RuledLine(etree.XSLTExtension):
  130.     
  131.     def execute(self, context, self_node, input_node, output_parent):
  132.         hr = etree.Element('hr')
  133.         output_parent.append(hr)
  134.  
  135.  
  136.  
  137. class TextBlock(etree.XSLTExtension):
  138.     
  139.     def __init__(self, styles, char_button_map, plot_map, log):
  140.         etree.XSLTExtension.__init__(self)
  141.         self.styles = styles
  142.         self.log = log
  143.         self.char_button_map = char_button_map
  144.         self.plot_map = plot_map
  145.  
  146.     
  147.     def execute(self, context, self_node, input_node, output_parent):
  148.         input_node = deepcopy(input_node)
  149.         div = etree.Element('div')
  150.         self.render_block(input_node, div)
  151.         output_parent.append(div)
  152.  
  153.     
  154.     def render_block(self, node, root):
  155.         ts = node.get('textstyle', None)
  156.         classes = []
  157.         bs = node.get('blockstyle')
  158.         if bs in self.styles.block_style_map:
  159.             classes.append('bs%d' % self.styles.block_style_map[bs])
  160.         
  161.         if ts in self.styles.text_style_map:
  162.             classes.append('ts%d' % self.styles.text_style_map[ts])
  163.         
  164.         if classes:
  165.             root.set('class', ' '.join(classes))
  166.         
  167.         objid = node.get('objid', None)
  168.         if objid:
  169.             root.set('id', objid)
  170.         
  171.         root.text = node.text
  172.         self.root = root
  173.         self.parent = root
  174.         self.add_text_to = (self.parent, 'text')
  175.         for child in node:
  176.             self.process_child(child)
  177.         
  178.  
  179.     
  180.     def add_text(self, text):
  181.         if text:
  182.             if getattr(self.add_text_to[0], self.add_text_to[1]) is None:
  183.                 setattr(self.add_text_to[0], self.add_text_to[1], '')
  184.             
  185.             setattr(self.add_text_to[0], self.add_text_to[1], getattr(self.add_text_to[0], self.add_text_to[1]) + text)
  186.         
  187.  
  188.     
  189.     def process_container(self, child, tgt):
  190.         idx = self.styles.get_text_styles(child)
  191.         if idx is not None:
  192.             tgt.set('class', 'ts%d' % idx)
  193.         
  194.         self.parent.append(tgt)
  195.         orig_parent = self.parent
  196.         self.parent = tgt
  197.         self.add_text_to = (self.parent, 'text')
  198.         self.add_text(child.text)
  199.         for gchild in child:
  200.             self.process_child(gchild)
  201.         
  202.         self.parent = orig_parent
  203.         self.add_text_to = (tgt, 'tail')
  204.         self.add_text(child.tail)
  205.  
  206.     
  207.     def process_child(self, child):
  208.         if child.tag == 'CR':
  209.             if self.parent == self.root or self.parent.tag == 'p':
  210.                 self.parent = self.root.makeelement('p')
  211.                 self.root.append(self.parent)
  212.                 self.add_text_to = (self.parent, 'text')
  213.             else:
  214.                 br = self.parent.makeelement('br')
  215.                 self.parent.append(br)
  216.                 self.add_text_to = (br, 'tail')
  217.             self.add_text(child.tail)
  218.         elif child.tag in ('P', 'Span', 'EmpLine', 'NoBR'):
  219.             span = self.root.makeelement('span')
  220.             if child.tag == 'EmpLine':
  221.                 td = None if child.get('emplineposition', 'before') == 'before' else 'overline'
  222.                 span.set('style', 'text-decoration: ' + td)
  223.             
  224.             self.process_container(child, span)
  225.         elif child.tag == 'Sup':
  226.             sup = self.root.makeelement('sup')
  227.             self.process_container(child, sup)
  228.         elif child.tag == 'Sub':
  229.             sub = self.root.makeelement('sub')
  230.             self.process_container(child, sub)
  231.         elif child.tag == 'Italic':
  232.             sup = self.root.makeelement('i')
  233.             self.process_container(child, sup)
  234.         elif child.tag == 'CharButton':
  235.             a = self.root.makeelement('a')
  236.             oid = child.get('refobj', None)
  237.             if oid in self.char_button_map:
  238.                 a.set('href', self.char_button_map[oid])
  239.             
  240.             self.process_container(child, a)
  241.         elif child.tag == 'Plot':
  242.             xsize = self.styles.to_num(child.get('xsize', None), 166 / 720)
  243.             ysize = self.styles.to_num(child.get('ysize', None), 166 / 720)
  244.             img = self.root.makeelement('img')
  245.             if xsize is not None:
  246.                 img.set('width', str(int(xsize)))
  247.             
  248.             if ysize is not None:
  249.                 img.set('height', str(int(ysize)))
  250.             
  251.             ro = child.get('refobj', None)
  252.             if ro in self.plot_map:
  253.                 img.set('src', self.plot_map[ro])
  254.             
  255.             self.parent.append(img)
  256.             self.add_text_to = (img, 'tail')
  257.             self.add_text(child.tail)
  258.         else:
  259.             self.log.warn('Unhandled Text element:', child.tag)
  260.  
  261.  
  262.  
  263. class Styles(etree.XSLTExtension):
  264.     
  265.     def __init__(self):
  266.         etree.XSLTExtension.__init__(self)
  267.         self.text_styles = []
  268.         self.block_styles = []
  269.         self.text_style_map = { }
  270.         self.block_style_map = { }
  271.         self.CSS = textwrap.dedent('\n        .image_page { text-align:center }\n        ')
  272.  
  273.     
  274.     def write(self, name = 'styles.css'):
  275.         
  276.         def join(style):
  277.             ans = [ '%s : %s;' % (k, v) for k, v in style.items() ]
  278.             return '\n\t'.join(ans)
  279.  
  280.         
  281.         try:
  282.             f = _[1]
  283.             f.write(self.CSS)
  284.             for w, sel in [
  285.                 (self.text_styles, 'ts'),
  286.                 (self.block_styles, 'bs')]:
  287.                 for i, s in enumerate(w):
  288.                     rsel = '.%s%d' % (sel, i)
  289.                     s = join(s)
  290.                     f.write(rsel + ' {\n\t' + s + '\n}\n\n')
  291.                 
  292.         finally:
  293.             pass
  294.  
  295.  
  296.     
  297.     def execute(self, context, self_node, input_node, output_parent):
  298.         if input_node.tag == 'TextStyle':
  299.             idx = self.get_text_styles(input_node)
  300.             if idx is not None:
  301.                 self.text_style_map[input_node.get('objid')] = idx
  302.             
  303.         else:
  304.             idx = self.get_block_styles(input_node)
  305.             self.block_style_map[input_node.get('objid')] = idx
  306.  
  307.     
  308.     def px_to_pt(self, px):
  309.         
  310.         try:
  311.             px = float(px)
  312.             return px * 72 / 166
  313.         except:
  314.             return None
  315.  
  316.  
  317.     
  318.     def color(self, val):
  319.         
  320.         try:
  321.             val = int(val, 16)
  322.             (r, g, b, a) = (val & 255, val >> 8 & 255, val >> 16 & 255, val >> 24 & 255)
  323.             if a == 255:
  324.                 return None
  325.             if a == 0:
  326.                 return 'rgb(%d,%d,%d)' % (r, g, b)
  327.             return 'rgba(%d,%d,%d,%f)' % (r, g, b, 1 - a / 255)
  328.         except:
  329.             return None
  330.  
  331.  
  332.     
  333.     def get_block_styles(self, node):
  334.         ans = { }
  335.         sm = self.px_to_pt(node.get('sidemargin', None))
  336.         if sm is not None:
  337.             ans['margin-left'] = ans['margin-right'] = '%fpt' % sm
  338.         
  339.         ts = self.px_to_pt(node.get('topskip', None))
  340.         if ts is not None:
  341.             ans['margin-top'] = '%fpt' % ts
  342.         
  343.         fs = self.px_to_pt(node.get('footskip', None))
  344.         if fs is not None:
  345.             ans['margin-bottom'] = '%fpt' % fs
  346.         
  347.         fw = self.px_to_pt(node.get('framewidth', None))
  348.         if fw is not None:
  349.             ans['border-width'] = '%fpt' % fw
  350.             ans['border-style'] = 'solid'
  351.         
  352.         fc = self.color(node.get('framecolor', None))
  353.         if fc is not None:
  354.             ans['border-color'] = fc
  355.         
  356.         bc = self.color(node.get('bgcolor', None))
  357.         if bc is not None:
  358.             ans['background-color'] = bc
  359.         
  360.         if ans not in self.block_styles:
  361.             self.block_styles.append(ans)
  362.         
  363.         return self.block_styles.index(ans)
  364.  
  365.     
  366.     def to_num(self, val, factor = 1):
  367.         
  368.         try:
  369.             return float(val) * factor
  370.         except:
  371.             return None
  372.  
  373.  
  374.     
  375.     def get_text_styles(self, node):
  376.         ans = { }
  377.         fs = self.to_num(node.get('fontsize', None), 0.1)
  378.         if fs is not None:
  379.             ans['font-size'] = '%fpt' % fs
  380.         
  381.         fw = self.to_num(node.get('fontweight', None))
  382.         if fw is not None:
  383.             ans['font-weight'] = None if fw >= 700 else 'normal'
  384.         
  385.         fg = self.color(node.get('textcolor', None))
  386.         if fg is not None:
  387.             ans['color'] = fg
  388.         
  389.         bg = self.color(node.get('textbgcolor', None))
  390.         if bg is not None:
  391.             ans['background-color'] = bg
  392.         
  393.         al = node.get('align', None)
  394.         if al is not None:
  395.             all = dict(head = 'left', center = 'center', foot = 'right')
  396.             ans['text-align'] = all.get(al, 'left')
  397.         
  398.         pi = self.to_num(node.get('parindent', None), 0.1)
  399.         if pi is not None:
  400.             ans['text-indent'] = '%fpt' % pi
  401.         
  402.         if not ans:
  403.             return None
  404.         if ans not in self.text_styles:
  405.             self.text_styles.append(ans)
  406.         
  407.         return self.text_styles.index(ans)
  408.  
  409.  
  410.  
  411. class LRFInput(InputFormatPlugin):
  412.     name = 'LRF Input'
  413.     author = 'Kovid Goyal'
  414.     description = 'Convert LRF files to HTML'
  415.     file_types = set([
  416.         'lrf'])
  417.     
  418.     def convert(self, stream, options, file_ext, log, accelerators):
  419.         self.log = log
  420.         self.log('Generating XML')
  421.         LRFDocument = LRFDocument
  422.         import calibre.ebooks.lrf.lrfparser
  423.         d = LRFDocument(stream)
  424.         d.parse()
  425.         xml = d.to_xml(write_files = True)
  426.         if options.verbose > 2:
  427.             open('lrs.xml', 'wb').write(xml.encode('utf-8'))
  428.         
  429.         parser = etree.XMLParser(no_network = True, huge_tree = True)
  430.         
  431.         try:
  432.             doc = etree.fromstring(xml, parser = parser)
  433.         except:
  434.             self.log.warn('Failed to parse XML. Trying to recover')
  435.             parser = etree.XMLParser(no_network = True, huge_tree = True, recover = True)
  436.             doc = etree.fromstring(xml, parser = parser)
  437.  
  438.         char_button_map = { }
  439.         for x in doc.xpath('//CharButton[@refobj]'):
  440.             ro = x.get('refobj')
  441.             jump_button = doc.xpath('//*[@objid="%s"]' % ro)
  442.             if jump_button:
  443.                 jump_to = jump_button[0].xpath('descendant::JumpTo[@refpage and @refobj]')
  444.                 if jump_to:
  445.                     char_button_map[ro] = '%s.xhtml#%s' % (jump_to[0].get('refpage'), jump_to[0].get('refobj'))
  446.                 
  447.             jump_to
  448.         
  449.         plot_map = { }
  450.         for x in doc.xpath('//Plot[@refobj]'):
  451.             ro = x.get('refobj')
  452.             image = doc.xpath('//Image[@objid="%s" and @refstream]' % ro)
  453.             if image:
  454.                 imgstr = doc.xpath('//ImageStream[@objid="%s" and @file]' % image[0].get('refstream'))
  455.                 if imgstr:
  456.                     plot_map[ro] = imgstr[0].get('file')
  457.                 
  458.             imgstr
  459.         
  460.         self.log('Converting XML to HTML...')
  461.         styledoc = etree.fromstring(P('templates/lrf.xsl', data = True))
  462.         media_type = MediaType()
  463.         styles = Styles()
  464.         text_block = TextBlock(styles, char_button_map, plot_map, log)
  465.         canvas = Canvas(doc, styles, text_block, log)
  466.         image_block = ImageBlock(canvas)
  467.         ruled_line = RuledLine()
  468.         extensions = {
  469.             ('calibre', 'media-type'): media_type,
  470.             ('calibre', 'text-block'): text_block,
  471.             ('calibre', 'ruled-line'): ruled_line,
  472.             ('calibre', 'styles'): styles,
  473.             ('calibre', 'canvas'): canvas,
  474.             ('calibre', 'image-block'): image_block }
  475.         transform = etree.XSLT(styledoc, extensions = extensions)
  476.         result = transform(doc)
  477.         
  478.         try:
  479.             f = _[1]
  480.             f.write(result)
  481.         finally:
  482.             pass
  483.  
  484.         styles.write()
  485.         return os.path.abspath('content.opf')
  486.  
  487.  
  488.