示例#1
0
 def __init__(self, parent, text = None, translator = None):
     parent += self
     self.text = text
     self.translator_cfg = translator
     if self.translator_cfg:
         self.translator = get_singleton(**self.translator_cfg)
     else:
         self.translator = None
示例#2
0
    def render(self, max_width, width_mode):
        # counting the calls is needed to decide if lines must be
        # deleted from cache in case of multiple rendering due to unresolved references.
        self.render_count += 1 
        
        # Instantiate the wrapper, if any
        if self.wrapper_cfg:
            self.wrapper_cfg['width'] = max_width
            # add optional hyphenator to the wrapper. this is
            # supported by textwrap2 which is part of the PyHyphen hyphenation library.
            if self.hyphenator_cfg:
                self.wrapper_cfg['use_hyphenator'] = self.hyphenator_cfg
            self.wrapper = get_singleton(**self.wrapper_cfg)
        else: self.wrapper = None
        
        # instantiate the optional translator. Note that each element may have
        # its own translator. However, the content manager's translator
        # works on the entire content rather than separately on each element.
        
        if self.translator_cfg:
            self.translator = get_singleton(**self.translator_cfg)
        else:
            self.translator = None
            
        # Render each element and put the results together. Future versions
        # may need to handle other content types.
        raw_content = []
        # containers for all refs and targets whether resolved or not
        self.refs = []
        self.targets = []
        given_pager = None # to store a potential Pager instance
        
        for child in self:
            if isinstance(child, GenericText):
                raw_content.append(child.render())
            elif isinstance(child, Reference):
                tmp = child.render()
                if not tmp:
                    if child.enabled: # unresolved Reference
                        tmp = u'{r' + unicode(len(self.refs)) + u'}'
                        self.refs.append(child)
                    else: tmp = u''
                raw_content.append(tmp)
            elif isinstance(child, Target):
                raw_content.append(u'{t' + unicode(len(self.targets)) + u'}')
                self.targets.append(child)
            elif isinstance(child, Pager):
                given_pager = child


        # Translate the frame's content altogether, if required,
        # skipping any placeholders for later substitution.
        if self.translator:
            i = 0
            previous_is_marker = False
            while i < len(raw_content):
                is_marker = markers_re.match(raw_content[i])
                if is_marker and is_marker.group() == raw_content[i]: # only then is it a reference or target marker
                    # check if previous element must be translated
                    if i > 0 and not previous_is_marker:
                        raw_content[i-1] = self.translator.run(raw_content[i-1])
                    previous_is_marker = True # retain this for next iteration
                    i += 1
                else:
                    # normal text:
                    # join with previous text element if any
                    if i == 0: i += 1
                    elif not previous_is_marker:
                        raw_content[i-1] += raw_content[i]
                        raw_content.pop(i)
                    previous_is_marker = False
                    
            # Translate the last text element
            if not previous_is_marker:
                raw_content[-1] = self.translator.run(raw_content[-1])
                    
        # join the translated results to a single string before wrapping it
        raw_content = u''.join(raw_content)
        
        # and wrap it into lines 
        if self.wrapper:
            raw_content = self.wrapper.wrap(raw_content)
        else: raw_content = [raw_content]
        
        # get the relevant width depending on the length of each
        # line and on whether width_mode is fixed or auto. The width is used when rendering each Line instance.
        # Note that due to unresolved references auto width can yield too large results at this stage.
        if width_mode == 'fixed': width = max_width
        else: # it must be 'auto':
            width = max((len(l) for l in raw_content))
        
        # Get the lines cache:
        root = self.parent.parent
        while not hasattr(root, 'cache'): root = root.parent
        cache = root.cache

        # pack the strings into Line objects.
        lrc = len(raw_content)
        for j in range(lrc):
            # check for reference and target markers
            # first, create containers for refs and targets to be passed on to the Lin instances
            cur_refs = []
            cur_targets = []
            # Iterate over any reference and target markers within the line:
            reftargets = ref_targets_re.finditer(raw_content[j])
            for r in reftargets:
                # extract the index of the Reference or Target object
                idx = int(r.group()[2:-1]) # this cuts off '{r' and '}'
                if r.group()[1] == u'r': # it is a reference
                    cur_refs.append(self.refs[idx])
                elif r.group()[1] == u't': # it is a target
                    cur_targets.append(self.targets[idx])
                    # delete the target marker. We do not need it anymore as we have found its Line instance
                    raw_content[j] = raw_content[j].replace(r.group(), u'')
                    
            # generate page break info to be used by the paginator:
            cur_pager = None
            if (j == 0) or (j == lrc - 2):
                cur_pager = Pager(self, mode = 2) # avoid widows and orphans
            if given_pager and (j == lrc - 1):
                cur_pager = given_pager

            # last line of paragraph should not be block-aligned by Line-render()
            if j == lrc - 1: last_in_para = True 
            else: last_in_para = False
            
            # Generate and store the Line instance
            cache.append(Line(raw_content[j], width, j,
                self.parent, self.x_align, last_in_para,
                refs = cur_refs, targets = cur_targets,
                pager = cur_pager))
            
        self.lines = raw_content # is this really needed?
        return (width, len(raw_content))