diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 20d5c3d62..cb65dc057 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -335,7 +335,7 @@ class Renderer(object): styled_text += styled_line html = self.page_shell + styled_text + HTML_END self.web.setHtml(html) - # Text too long so go to next page + # Text too long so go to next page. if self.web_frame.contentsSize().height() > self.page_height: if force_page and line_count > 0: Receiver.send_message(u'theme_line_count', line_count) @@ -366,7 +366,7 @@ class Renderer(object): """ log.debug(u'_paginate_slide_words - Start') - line_end = u'' + line_end = u' ' if line_break: line_end = u'
' formatted = [] @@ -374,10 +374,11 @@ class Renderer(object): previous_raw = u'' lines = text.split(u'\n') for line in lines: + line = line.strip() styled_line = expand_tags(line) html = self.page_shell + previous_html + styled_line + HTML_END self.web.setHtml(html) - # Text too long so go to next page + # Text too long so go to next page. if self.web_frame.contentsSize().height() > self.page_height: # Check if there was a verse before the current one and append # it, when it fits on the page. @@ -401,24 +402,56 @@ class Renderer(object): previous_html = styled_line + line_end previous_raw = line + line_end continue - words = self._words_split(line) - for word in words: - styled_word = expand_tags(word) - html = self.page_shell + previous_html + styled_word + \ - HTML_END + # Figure out how many words of the line will fit on screen by + # using the algorithm known as "binary chop". + raw_words = self._words_split(line) + html_words = [expand_tags(word) for word in raw_words] + smallest_index = 0 + highest_index = len(html_words) - 1 + index = int(highest_index / 2) + while True: + html = self.page_shell + previous_html + \ + u''.join(html_words[:index + 1]).strip() + HTML_END self.web.setHtml(html) - # Text too long so go to next page if self.web_frame.contentsSize().height() > \ self.page_height: - while previous_raw.endswith(u'
'): - previous_raw = previous_raw[:-4] - formatted.append(previous_raw) + # We know that it does not fit, so change/calculate the + # new index and highest_index accordingly. + highest_index = index + index = int(index - (index - smallest_index) / 2) + else: + smallest_index = index + index = int(index + (highest_index - index) / 2) + # We found the number of words which will fit. + if smallest_index == index or highest_index == index: + index = smallest_index + formatted.append(previous_raw.rstrip(u'
') + + u''.join(raw_words[:index + 1])) previous_html = u'' previous_raw = u'' - previous_html += styled_word - previous_raw += word - previous_html += line_end - previous_raw += line_end + else: + continue + # Check if the rest of the line fits on the slide. If it + # does we do not have to do the much more intensive "word by + # word" checking. + html = self.page_shell + \ + u''.join(html_words[index + 1:]).strip() + HTML_END + self.web.setHtml(html) + if self.web_frame.contentsSize().height() <= \ + self.page_height: + previous_html = \ + u''.join(html_words[index + 1:]).strip() + line_end + previous_raw = \ + u''.join(raw_words[index + 1:]).strip() + line_end + break + else: + # The other words do not fit, thus reset the indexes, + # create a new list and continue with "word by word". + raw_words = raw_words[index + 1:] + html_words = html_words[index + 1:] + smallest_index = 0 + highest_index = len(html_words) - 1 + index = int(highest_index / 2) else: previous_html += styled_line + line_end previous_raw += line + line_end