web/xhtml2fo.py
branch3.5
changeset 2935 e06b3eadef31
child 2936 f35b64718d02
equal deleted inserted replaced
2934:cf4d39416fca 2935:e06b3eadef31
       
     1 from cubicweb.utils import can_do_pdf_conversion
       
     2 assert can_do_pdf_conversion()
       
     3 
       
     4 from xml.etree.ElementTree import QName, fromstring
       
     5 from pyxmltrf.standard.xhtml_xslfo.transformer import XHTML2FOTransformer
       
     6 from pyxmltrf.utils.xslfo.standard import cm
       
     7 from pyxmltrf.utils.xslfo import SimplePageMaster
       
     8 from pyxmltrf.standard.xhtml_xslfo.default_styling import default_styles
       
     9 from pyxmltrf.standard.xhtml_xslfo import XHTML_NS
       
    10 
       
    11 
       
    12 class ReportTransformer(XHTML2FOTransformer):
       
    13     """
       
    14     Class transforming an XHTML input tree into a FO document
       
    15     displaying reports (one report for each <div class="contentmain">
       
    16     element in the input tree.
       
    17     """
       
    18 
       
    19     def __init__(self, section,
       
    20                  page_width=21.0, page_height=29.7,
       
    21                  margin_top=1.0, margin_bottom=1.0,
       
    22                  margin_left=1.0, margin_right=1.0,
       
    23                  header_footer_height=0.75,
       
    24                  standard_font_size=11.0, default_lang=u"fr" ):
       
    25         """
       
    26         Initializes a transformer turning an XHTML input tree
       
    27         containing <div class="contentmain"> elements representing
       
    28         main content sections into a FO output tree displaying the
       
    29         reports.
       
    30 
       
    31         page_width: float - width of the page (in cm)
       
    32         page_height: float - height of the page (in cm)
       
    33         margin_top: float - top margin of the page (in cm)
       
    34         margin_bottom: float - bottom margin of the page (in cm)
       
    35         margin_left: float - left margin of the page (in cm)
       
    36         margin_right: float - right margin of the page (in cm)
       
    37         header_footer_height: float - height of the header or the footer of the
       
    38                               page that the page number (if any) will be
       
    39                               inserted in.
       
    40         standard_font_size: float - standard size of the font (in pt)
       
    41         default_lang: u"" - default language (used for hyphenation)
       
    42         """
       
    43         self.section = section
       
    44         self.page_width = page_width
       
    45         self.page_height = page_height
       
    46 
       
    47         self.page_tmargin = margin_top
       
    48         self.page_bmargin = margin_bottom
       
    49         self.page_lmargin = margin_left
       
    50         self.page_rmargin = margin_right
       
    51 
       
    52         self.hf_height = header_footer_height
       
    53 
       
    54         self.font_size = standard_font_size
       
    55         self.lang = default_lang
       
    56 
       
    57         XHTML2FOTransformer.__init__(self)
       
    58 
       
    59 
       
    60     def define_pagemasters(self):
       
    61         """
       
    62         Defines the page masters for the FO output document.
       
    63         """
       
    64         pm = SimplePageMaster(u"page-report")
       
    65         pm.set_page_dims( self.page_width*cm, self.page_height*cm )
       
    66         pm.set_page_margins({u'top'   : self.page_tmargin*cm,
       
    67                              u'bottom': self.page_bmargin*cm,
       
    68                              u'left'  : self.page_lmargin*cm,
       
    69                              u'right' : self.page_rmargin*cm })
       
    70         pm.add_peripheral_region(u"end",self.hf_height)
       
    71         dims = {}
       
    72         dims[u"bottom"] = self.hf_height + 0.25
       
    73         pm.set_main_region_margins(dims)
       
    74         return [pm]
       
    75 
       
    76     def _visit_report(self, in_elt, _out_elt, params):
       
    77         """
       
    78         Specific visit function for the input <div> elements whose class is
       
    79         "report". The _root_visit method of this class selects these input
       
    80         elements and asks the process of these elements with this specific
       
    81         visit function.
       
    82         """
       
    83 
       
    84         ps = self.create_pagesequence(u"page-report")
       
    85         props = { u"force-page-count": u"no-force",
       
    86                   u"initial-page-number": u"1",
       
    87                   u"format": u"1", }
       
    88         self._output_properties(ps,props)
       
    89 
       
    90         sc = self.create_staticcontent(ps, u"end")
       
    91         sc_bl = self.create_block(sc)
       
    92         attrs = { u"hyphenate": u"false", }
       
    93         attrs[u"font-size"] = u"%.1fpt" %(self.font_size*0.7)
       
    94         attrs[u"language"] = self.lang
       
    95         attrs[u"text-align"] = u"center"
       
    96         self._output_properties(sc_bl,attrs)
       
    97         sc_bl.text = u"Page" + u" " # ### Should be localised!
       
    98         pn = self.create_pagenumber(sc_bl)
       
    99         pn.tail = u"/"
       
   100         lpn = self.create_pagenumbercitation( sc_bl,
       
   101                                               u"last-block-of-report-%d" % params[u"context_pos"]
       
   102                                               )
       
   103 
       
   104 
       
   105         fl = self.create_flow(ps,u"body")
       
   106         bl = self.create_block(fl)
       
   107 
       
   108         # Sets on the highest block element the properties of the XHTML body
       
   109         # element. These properties (at the least the inheritable ones) will
       
   110         # be inherited by all the future FO elements.
       
   111         bodies = list(self.in_tree.getiterator(QName(XHTML_NS,u"body")))
       
   112         if len(bodies) > 0:
       
   113             attrs = self._extract_properties([bodies[0]])
       
   114         else:
       
   115             attrs = default_styles[u"body"].copy()
       
   116         attrs[u"font-size"] = u"%.1fpt" %self.font_size
       
   117         attrs[u"language"] = self.lang
       
   118         self._output_properties(bl,attrs)
       
   119 
       
   120         # Processes the report content
       
   121         self._copy_text(in_elt,bl)
       
   122         self._process_nodes(in_elt.getchildren(),bl)
       
   123 
       
   124         # Inserts an empty block at the end of the report in order to be able
       
   125         # to compute the last page number of this report.
       
   126         last_bl = self.create_block(bl)
       
   127         props = { u"keep-with-previous": u"always", }
       
   128         props[u"id"] = u"last-block-of-report-%d" % params[u"context_pos"]
       
   129         self._output_properties(last_bl,props)
       
   130 
       
   131 
       
   132     def _root_visit(self):
       
   133         """
       
   134         Visit function called when starting the process of the input tree.
       
   135         """
       
   136         content = [ d for d in self.in_tree.getiterator(QName(XHTML_NS,u"div"))
       
   137                     if d.get(u"id") == self.section ]
       
   138         # Asks the process of the report elements with a specific visit
       
   139         # function
       
   140         self._process_nodes(content, self.fo_root,
       
   141                             with_function=self._visit_report)
       
   142