← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~googol-hush/openlp/render into lp:openlp

 

Andreas Preikschat has proposed merging lp:~googol-hush/openlp/render into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~googol-hush/openlp/render/+merge/62017

Hello,

New 'word by word' algorithm

This introduces a new algorithm for the "word by word" rendering. This algorithm has weaknesses and strengths (as well as the trunk implementation). It works like this:

Let us play a game. I think of a number between 1 and 100 and you have to figure out what number I am thinking of. The winner is the one who need fewer attempts. How do you proceed?

You: Is the number you are thinking of lower than 50?
Me: No, it is not.
You: Is the number lower than 75?
Me No, it is not.
You: Is the number lower than 87?
Me: Yes, it is.
You: Is the number lower than 81?
...
...

Basically that is what I have done here. I have some test data and a diagram for you (rendering Genesis 1 at different font sizes).

Diagram: http://ubuntuone.com/p/v7G/
Test Results: http://ubuntuone.com/p/v7N/

It is obvious that at 30px the average verse will fit on a slide (so we do not need to process "word by word"). The new algorithm is much better than trunk as long as the font size is below 130px.

Please, test it! The danger in rendering the text like this is, that it is less simple and an error in the algorithm can mean that it "eats" single words of a verse.
-- 
https://code.launchpad.net/~googol-hush/openlp/render/+merge/62017
Your team OpenLP Core is requested to review the proposed merge of lp:~googol-hush/openlp/render into lp:openlp.
=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py	2011-05-17 18:55:45 +0000
+++ openlp/core/lib/renderer.py	2011-05-23 18:50:32 +0000
@@ -335,7 +335,7 @@
             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 @@
 
         """
         log.debug(u'_paginate_slide_words - Start')
-        line_end = u''
+        line_end = u' '
         if line_break:
             line_end = u'<br>'
         formatted = []
@@ -374,10 +374,11 @@
         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,59 @@
                             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.
+                # Instead of just looping of the list of words we follow a
+                # certain tactic, namely we try if the half of line fits. If it
+                # does we try if the half of the other half and the first half
+                # (75%) will still fit. In the case that the first half does not
+                # fit, we try if 25% will fit.
+                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'<br>'):
-                            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:
+                        formatted.append(previous_raw.rstrip(u'<br>') +
+                            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


Follow ups