diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 1b94e7896..ac7e95c4c 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -46,8 +46,6 @@ VERSE = u'The Lord said to {r}Noah{/r}: \n' \ 'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n' FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456'] -HTML_END = u'' - class Renderer(object): """ Class to pull all Renderer interactions into one place. The plugins will @@ -85,7 +83,7 @@ class Renderer(object): Updates the render manager's information about the current screen. """ log.debug(u'Update Display') - self._calculate_default(self.screens.current[u'size']) + self._calculate_default() if self.display: self.display.close() self.display = MainDisplay(None, self.imageManager, False) @@ -163,7 +161,7 @@ class Renderer(object): self.theme_data = override_theme else: self.theme_data = self.themeManager.getThemeData(theme) - self._calculate_default(self.screens.current[u'size']) + self._calculate_default() self._build_text_rectangle(self.theme_data) # if No file do not update cache if self.theme_data.background_filename: @@ -185,7 +183,7 @@ class Renderer(object): # save value for use in format_slide self.force_page = force_page # set the default image size for previews - self._calculate_default(self.screens.preview[u'size']) + self._calculate_default() # build a service item to generate preview serviceItem = ServiceItem() serviceItem.theme = theme_data @@ -203,7 +201,7 @@ class Renderer(object): raw_html = serviceItem.get_rendered_frame(0) preview = self.display.text(raw_html) # Reset the real screen size for subsequent render requests - self._calculate_default(self.screens.current[u'size']) + self._calculate_default() return preview self.force_page = False @@ -224,7 +222,7 @@ class Renderer(object): line_end = u' ' # Bibles if item.is_capable(ItemCapabilities.AllowsWordSplit): - pages = self._paginate_slide_words(text, line_end) + pages = self._paginate_slide_words(text.split(u'\n'), line_end) else: # Clean up line endings. lines = self._lines_split(text) @@ -245,19 +243,16 @@ class Renderer(object): new_pages.append(page) return new_pages - def _calculate_default(self, screen): + def _calculate_default(self): """ Calculate the default dimentions of the screen. - - ``screen`` - The screen to calculate the default of. """ - log.debug(u'_calculate default %s', screen) - self.width = screen.width() - self.height = screen.height() + screen_size = self.screens.current[u'size'] + self.width = screen_size.width() + self.height = screen_size.height() self.screen_ratio = float(self.height) / float(self.width) - log.debug(u'calculate default %d, %d, %f', - self.width, self.height, self.screen_ratio) + log.debug(u'_calculate default %s, %f' % (screen_size, + self.screen_ratio)) # 90% is start of footer self.footer_start = int(self.height * 0.90) @@ -310,17 +305,28 @@ class Renderer(object): self.web.resize(self.page_width, self.page_height) self.web_frame = self.web.page().mainFrame() # Adjust width and height to account for shadow. outline done in css - self.page_shell = u'' \ - u'
' % \ + html = u""" +
""" % \ (build_lyrics_format_css(self.theme_data, self.page_width, self.page_height), build_lyrics_outline_css(self.theme_data)) + self.web.setHtml(html) def _paginate_slide(self, lines, line_end): """ Figure out how much text can appear on a slide, using the current theme settings. + **Note:** The smallest possible "unit" of text for a slide is one line. + If the line is too long it will be cut off when displayed. ``lines`` The text to be fitted on the slide split into lines. @@ -334,10 +340,8 @@ class Renderer(object): previous_raw = u'' separator = u'
' html_lines = map(expand_tags, lines) - html = self.page_shell + separator.join(html_lines) + HTML_END - self.web.setHtml(html) # Text too long so go to next page. - if self.web_frame.contentsSize().height() > self.page_height: + if self._text_fits_on_slide(separator.join(html_lines)): html_text, previous_raw = self._binary_chop(formatted, previous_html, previous_raw, html_lines, lines, separator, u'') else: @@ -347,48 +351,41 @@ class Renderer(object): log.debug(u'_paginate_slide - End') return formatted - def _paginate_slide_words(self, text, line_end): + def _paginate_slide_words(self, lines, line_end): """ Figure out how much text can appear on a slide, using the current - theme settings. This version is to handle text which needs to be split - into words to get it to fit. + theme settings. + **Note:** The smallest possible "unit" of text for a slide is one word. + If one line is too long it will be processed word by word. This is + sometimes need for **bible** verses. - ``text`` - The words to be fitted on the slide split into lines. + ``lines`` + The text to be fitted on the slide split into lines. ``line_end`` The text added after each line. Either ``u' '`` or ``u'
``. - This is needed for bibles. + This is needed for **bibles**. """ log.debug(u'_paginate_slide_words - Start') formatted = [] previous_html = u'' previous_raw = u'' - lines = text.split(u'\n') for line in lines: line = line.strip() html_line = expand_tags(line) - html = self.page_shell + previous_html + html_line + HTML_END - self.web.setHtml(html) # Text too long so go to next page. - if self.web_frame.contentsSize().height() > self.page_height: + if self._text_fits_on_slide(previous_html + html_line): # Check if there was a verse before the current one and append # it, when it fits on the page. if previous_html: - html = self.page_shell + previous_html + HTML_END - self.web.setHtml(html) - if self.web_frame.contentsSize().height() <= \ - self.page_height: + if not self._text_fits_on_slide(previous_html): formatted.append(previous_raw) previous_html = u'' previous_raw = u'' - html = self.page_shell + html_line + HTML_END - self.web.setHtml(html) # Now check if the current verse will fit, if it does # not we have to start to process the verse word by # word. - if self.web_frame.contentsSize().height() <= \ - self.page_height: + if not self._text_fits_on_slide(html_line): previous_html = html_line + line_end previous_raw = line + line_end continue @@ -445,10 +442,8 @@ class Renderer(object): highest_index = len(html_list) - 1 index = int(highest_index / 2) while True: - html = self.page_shell + previous_html + \ - separator.join(html_list[:index + 1]).strip() + HTML_END - self.web.setHtml(html) - if self.web_frame.contentsSize().height() > self.page_height: + if self._text_fits_on_slide( + previous_html + separator.join(html_list[:index + 1]).strip()): # We know that it does not fit, so change/calculate the # new index and highest_index accordingly. highest_index = index @@ -470,10 +465,8 @@ class Renderer(object): else: continue # Check if the remaining elements fit on the slide. - html = self.page_shell + \ - separator.join(html_list[index + 1:]).strip() + HTML_END - self.web.setHtml(html) - if self.web_frame.contentsSize().height() <= self.page_height: + if not self._text_fits_on_slide( + separator.join(html_list[index + 1:]).strip()): previous_html = separator.join( html_list[index + 1:]).strip() + line_end previous_raw = separator.join( @@ -489,6 +482,18 @@ class Renderer(object): index = int(highest_index / 2) return previous_html, previous_raw + def _text_fits_on_slide(self, text): + """ + Checks if the given ``text`` fits on a slide. If it does ``True`` is + returned, otherwise ``False``. + + ``text`` + The text to check. It can contain HTML tags. + """ + self.web_frame.evaluateJavaScript(u'show_text("%s")' % + text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"')) + return self.web_frame.contentsSize().height() > self.page_height + def _words_split(self, line): """ Split the slide up by word so can wrap better diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index d5603c31f..9904868ce 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -188,7 +188,7 @@ class MainDisplay(QtGui.QGraphicsView): while not self.webLoaded: Receiver.send_message(u'openlp_process_events') self.setGeometry(self.screen[u'size']) - self.frame.evaluateJavaScript(u'show_text("%s")' % \ + self.frame.evaluateJavaScript(u'show_text("%s")' % slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"')) return self.preview()