started improving renderer speed

This commit is contained in:
Andreas Preikschat 2011-06-12 21:27:19 +02:00
commit 3c29367223
2 changed files with 100 additions and 71 deletions

View File

@ -328,30 +328,25 @@ class Renderer(object):
if line_break:
line_end = u'<br>'
formatted = []
html_text = u''
styled_text = u''
line_count = 0
for line in lines:
if line_count != -1:
line_count += 1
styled_line = expand_tags(line) + line_end
styled_text += styled_line
html = self.page_shell + styled_text + HTML_END
self.web.setHtml(html)
# 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 - 1)
line_count = -1
while html_text.endswith(u'<br>'):
html_text = html_text[:-4]
formatted.append(html_text)
html_text = u''
styled_text = styled_line
html_text += line + line_end
while html_text.endswith(u'<br>'):
html_text = html_text[:-4]
formatted.append(html_text)
previous_html = u''
previous_raw = u''
lines = [u'%s<br>' % line for line in lines]
html_lines = map(expand_tags, lines)
html = self.page_shell + u''.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:
html_text, previous_raw, index = self._binary_chop(
formatted, previous_html, previous_raw, html_lines, lines,
line_end)
if force_page:
Receiver.send_message(u'theme_line_count', index + 1)
else:
previous_raw = u''.join(lines)
while previous_raw.endswith(u'<br>'):
previous_raw = previous_raw[:-4]
if previous_raw:
formatted.append(previous_raw)
log.debug(u'_paginate_slide - End')
return formatted
@ -408,53 +403,10 @@ class Renderer(object):
# 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)
if self.web_frame.contentsSize().height() > \
self.page_height:
# 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'<br>') +
u''.join(raw_words[:index + 1]))
previous_html = u''
previous_raw = u''
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)
html_words = map(expand_tags, raw_text)
previous_html, previous_raw, index = self._binary_chop(
formatted, previous_html, previous_raw, html_words,
raw_words, line_end)
else:
previous_html += styled_line + line_end
previous_raw += line + line_end
@ -464,6 +416,79 @@ class Renderer(object):
log.debug(u'_paginate_slide_words - End')
return formatted
def _binary_chop(self, formatted, previous_html, previous_raw, html_list,
raw_list, line_end):
"""
This implements the binary chop algorithm for faster rendering. However,
it is assumed that this method is **only** called, when the text to be
rendered does not fit as a whole.
``formatted``
The list of slides.
``previous_html``
The html text which is know to fit on a slide, but is not yet added
to the list of slides. (unicode string)
``previous_raw``
The raw text (with display tags) which is know to fit on a slide,
but is not yet added to the list of slides. (unicode string)
``html_list``
``raw_list``
The text which does not fit on a slide and needs to be processed
using the binary chop. The text can contain display tags.
``line_end``
The
"""
smallest_index = 0
highest_index = len(html_list) - 1
index = int(highest_index / 2)
while True:
html = self.page_shell + previous_html + \
u''.join(html_list[:index + 1]).strip() + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() > self.page_height:
# 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'<br>') +
u''.join(raw_list[:index + 1]))
previous_html = u''
previous_raw = u''
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_list[index + 1:]).strip() + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() <= self.page_height:
previous_html = \
u''.join(html_list[index + 1:]).strip() + line_end
previous_raw = u''.join(raw_list[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_list = raw_list[index + 1:]
html_list = html_list[index + 1:]
smallest_index = 0
highest_index = len(html_list) - 1
index = int(highest_index / 2)
return previous_html, previous_raw, index
def _words_split(self, line):
"""
Split the slide up by word so can wrap better

View File

@ -172,6 +172,9 @@ class ServiceItem(object):
self.themedata = self.renderer.theme_data
if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides')
import time
import datetime
start = time.time()
for slide in self._raw_frames:
formatted = self.renderer \
.format_slide(slide[u'raw_slide'], line_break, self)
@ -184,6 +187,7 @@ class ServiceItem(object):
u'html': html.replace(u'&amp;nbsp;', u'&nbsp;'),
u'verseTag': slide[u'verseTag']
})
print unicode(datetime.timedelta(seconds=time.time() - start))
elif self.service_item_type == ServiceItemType.Image or \
self.service_item_type == ServiceItemType.Command:
pass