add OOS code and speed up renderer

Add re-theming in servicemanager when theme changes.
Sort out Renderer to prevent not relevent calls

bzr-revno: 465
This commit is contained in:
Tim Bentley 2009-06-10 17:34:50 +01:00
commit 356c788537
5 changed files with 70 additions and 74 deletions

View File

@ -46,6 +46,7 @@ class Renderer:
self._frame = None self._frame = None
self._bg_frame = None self._bg_frame = None
self.bg_image = None self.bg_image = None
self._bg_frame_small = None
def set_debug(self, debug): def set_debug(self, debug):
self._debug=debug self._debug=debug
@ -57,7 +58,9 @@ class Renderer:
log.debug(u'set theme') log.debug(u'set theme')
self._theme = theme self._theme = theme
self._bg_frame = None self._bg_frame = None
self.bg_image = None
self.theme_name = theme.theme_name self.theme_name = theme.theme_name
self._set_theme_font()
if theme.background_type == u'image': if theme.background_type == u'image':
if theme.background_filename is not None: if theme.background_filename is not None:
self.set_bg_image(theme.background_filename) self.set_bg_image(theme.background_filename)
@ -95,7 +98,7 @@ class Renderer:
log.debug(u'set frame dest (frame) w %d h %d', frame_width, frame_height) log.debug(u'set frame dest (frame) w %d h %d', frame_width, frame_height)
self._frame = QtGui.QImage(frame_width, frame_height, self._frame = QtGui.QImage(frame_width, frame_height,
QtGui.QImage.Format_ARGB32_Premultiplied) QtGui.QImage.Format_ARGB32_Premultiplied)
if self._bg_image_filename is not None: if self._bg_image_filename is not None and self.bg_image is None:
self.scale_bg_image() self.scale_bg_image()
if self._bg_frame is None: if self._bg_frame is None:
self._generate_background_frame() self._generate_background_frame()
@ -104,8 +107,7 @@ class Renderer:
""" """
External API to sort out the text to pe placed on the frame External API to sort out the text to pe placed on the frame
""" """
#print "########## Format Slide ##################" log.debug(u'format_slide - Start')
log.debug(u'format_slide %s', words)
verses = [] verses = []
words = words.replace(u'\r\n', u'\n') words = words.replace(u'\r\n', u'\n')
verses_text = words.split(u'\n\n') verses_text = words.split(u'\n\n')
@ -115,8 +117,7 @@ class Renderer:
for line in lines: for line in lines:
text.append(line) text.append(line)
split_text = self._split_set_of_lines(text, False) split_text = self._split_set_of_lines(text, False)
#print "split text ", split_text log.debug(u'format_slide - End')
#print "text ", text
return split_text return split_text
def set_text_rectangle(self, rect_main, rect_footer): def set_text_rectangle(self, rect_main, rect_footer):
@ -136,12 +137,16 @@ class Renderer:
bbox = self._render_lines_unaligned(lines, False) bbox = self._render_lines_unaligned(lines, False)
if footer_lines is not None: if footer_lines is not None:
bbox1 = self._render_lines_unaligned(footer_lines, True) bbox1 = self._render_lines_unaligned(footer_lines, True)
# reset the frame. first time do not worry about what you paint on.
#self._frame = QtGui.QPixmap(self._frame.width(), self._frame.height()) #(self._bg_frame)
#self._frame.fill(QtCore.Qt.transparent)
# reset the frame. first time do not worrk about what you paint on. # reset the frame. first time do not worrk about what you paint on.
self._frame = QtGui.QImage(self._bg_frame) self._frame = QtGui.QImage(self._bg_frame)
x, y = self._correctAlignment(self._rect, bbox) x, y = self._correctAlignment(self._rect, bbox)
bbox = self._render_lines_unaligned(lines, False, (x, y)) bbox = self._render_lines_unaligned(lines, False, (x, y), True)
if footer_lines is not None: if footer_lines is not None:
bbox = self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()) ) bbox = self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()), True )
log.debug(u'generate_frame_from_lines - Finish')
return self._frame return self._frame
def _generate_background_frame(self): def _generate_background_frame(self):
@ -152,7 +157,7 @@ class Renderer:
assert(self._theme) assert(self._theme)
self._bg_frame = QtGui.QImage(self._frame.width(), self._frame.height(), self._bg_frame = QtGui.QImage(self._frame.width(), self._frame.height(),
QtGui.QImage.Format_ARGB32_Premultiplied) QtGui.QImage.Format_ARGB32_Premultiplied)
log.debug(u'render background %s ', self._theme.background_type) log.debug(u'render background %s start', self._theme.background_type)
painter = QtGui.QPainter() painter = QtGui.QPainter()
painter.begin(self._bg_frame) painter.begin(self._bg_frame)
if self._theme.background_type == u'solid': if self._theme.background_type == u'solid':
@ -186,6 +191,9 @@ class Renderer:
if self.bg_image is not None: if self.bg_image is not None:
painter.drawImage(0 ,0 , self.bg_image) painter.drawImage(0 ,0 , self.bg_image)
painter.end() painter.end()
self._bg_frame_small = self._bg_frame.scaled(QtCore.QSize(280, 210), QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
log.debug(u'render background End')
def _split_set_of_lines(self, lines, footer): def _split_set_of_lines(self, lines, footer):
""" """
@ -196,10 +204,8 @@ class Renderer:
Returns a list of [lists of lines], one set for each screenful Returns a list of [lists of lines], one set for each screenful
""" """
bboxes = [] bboxes = []
#print "lines ", lines
for line in lines: for line in lines:
bboxes.append(self._render_and_wrap_single_line(line, footer)) bboxes.append(self._render_and_wrap_single_line(line, footer))
#print "bboxes ", bboxes
numlines = len(lines) numlines = len(lines)
bottom = self._rect.bottom() bottom = self._rect.bottom()
for ratio in (numlines, numlines/2, numlines/3, numlines/4): for ratio in (numlines, numlines/2, numlines/3, numlines/4):
@ -209,9 +215,7 @@ class Renderer:
while (endline <= numlines and endline != 0): while (endline <= numlines and endline != 0):
by = 0 by = 0
for (x,y) in bboxes[startline:endline]: for (x,y) in bboxes[startline:endline]:
#print by, startline, endline, x, y, bottom
by += y by += y
#print "by ", by , bottom, startline, endline, numlines, ratio
if by > bottom: if by > bottom:
good = 0 good = 0
break break
@ -221,20 +225,17 @@ class Renderer:
break break
retval = [] retval = []
numlines_per_page = ratio numlines_per_page = ratio
#print "good ", good, ratio
if good: if good:
c = 0 c = 0
thislines = [] thislines = []
while c < numlines: while c < numlines:
thislines.append(lines[c]) thislines.append(lines[c])
c += 1 c += 1
#print "c ", c, len(thislines), numlines_per_page, thislines
if len(thislines) == numlines_per_page: if len(thislines) == numlines_per_page:
retval.append(thislines) retval.append(thislines)
thislines = [] thislines = []
if len(thislines) > 0: if len(thislines) > 0:
retval.append(thislines) retval.append(thislines)
#print "extra ", thislines
else: else:
# print "Just split where you can" # print "Just split where you can"
retval = [] retval = []
@ -251,7 +252,6 @@ class Renderer:
endline = startline endline = startline
by = 0 by = 0
endline += 1 endline += 1
#print "retval ", retval
return retval return retval
def _correctAlignment(self, rect, bbox): def _correctAlignment(self, rect, bbox):
@ -266,7 +266,7 @@ class Renderer:
log.error(u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign) log.error(u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
return x, y return x, y
def _render_lines_unaligned(self, lines, footer, tlcorner=(0,0)): def _render_lines_unaligned(self, lines, footer, tlcorner=(0,0), live=False):
""" """
Given a list of lines to render, render each one in turn Given a list of lines to render, render each one in turn
(using the _render_single_line fn - which may result in going (using the _render_single_line fn - which may result in going
@ -274,14 +274,13 @@ class Renderer:
than a screenful (eg. by using split_set_of_lines) than a screenful (eg. by using split_set_of_lines)
Returns the bounding box of the text as QRect Returns the bounding box of the text as QRect
""" """
log.debug(u'render lines unaligned Start')
x, y = tlcorner x, y = tlcorner
brx = x brx = x
bry = y bry = y
for line in lines: for line in lines:
# render after current bottom, but at original left edge # render after current bottom, but at original left edge
# keep track of right edge to see which is biggest # keep track of right edge to see which is biggest
(thisx, bry) = self._render_and_wrap_single_line(line, footer, (x , bry)) (thisx, bry) = self._render_and_wrap_single_line(line, footer, (x , bry), live)
if (thisx > brx): if (thisx > brx):
brx = thisx brx = thisx
retval = QtCore.QRect(x, y,brx-x, bry-y) retval = QtCore.QRect(x, y,brx-x, bry-y)
@ -293,7 +292,7 @@ class Renderer:
painter.end() painter.end()
return retval return retval
def _render_and_wrap_single_line(self, line, footer, tlcorner=(0,0)): def _render_and_wrap_single_line(self, line, footer, tlcorner=(0,0), live=False):
""" """
Render a single line of words onto the DC, top left corner Render a single line of words onto the DC, top left corner
specified. specified.
@ -301,7 +300,6 @@ class Renderer:
right-aligns the surplus words in the manner of song lyrics right-aligns the surplus words in the manner of song lyrics
Returns the bottom-right corner (of what was rendered) as a tuple(x, y). Returns the bottom-right corner (of what was rendered) as a tuple(x, y).
""" """
#log.debug(u'Render single line %s @ %s '%( line, tlcorner))
x, y = tlcorner x, y = tlcorner
# We draw the text to see how big it is and then iterate to make it fit # We draw the text to see how big it is and then iterate to make it fit
# when we line wrap we do in in the "lyrics" style, so the second line is # when we line wrap we do in in the "lyrics" style, so the second line is
@ -359,29 +357,30 @@ class Renderer:
elif align == 2: elif align == 2:
x = (maxx - w) / 2; x = (maxx - w) / 2;
rightextent = x + w rightextent = x + w
# now draw the text, and any outlines/shadows if live:
if self._theme.display_shadow: # now draw the text, and any outlines/shadows
self._get_extent_and_render(line, footer, tlcorner=(x+self._shadow_offset,y+self._shadow_offset), if self._theme.display_shadow:
draw=True, color = self._theme.display_shadow_color) self._get_extent_and_render(line, footer, tlcorner=(x+self._shadow_offset,y+self._shadow_offset),
if self._theme.display_outline: draw=True, color = self._theme.display_shadow_color)
self._get_extent_and_render(line, footer, (x+self._outline_offset,y), draw=True, if self._theme.display_outline:
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x+self._outline_offset,y), draw=True,
self._get_extent_and_render(line, footer, (x, y+self._outline_offset), draw=True, color = self._theme.display_outline_color)
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x, y+self._outline_offset), draw=True,
self._get_extent_and_render(line, footer, (x, y-self._outline_offset), draw=True, color = self._theme.display_outline_color)
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x, y-self._outline_offset), draw=True,
self._get_extent_and_render(line, footer, (x-self._outline_offset,y), draw=True, color = self._theme.display_outline_color)
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x-self._outline_offset,y), draw=True,
if self._outline_offset > 1: color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer, (x+self._outline_offset,y+self._outline_offset), draw=True, if self._outline_offset > 1:
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x+self._outline_offset,y+self._outline_offset), draw=True,
self._get_extent_and_render(line, footer, (x-self._outline_offset,y+self._outline_offset), draw=True, color = self._theme.display_outline_color)
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x-self._outline_offset,y+self._outline_offset), draw=True,
self._get_extent_and_render(line, footer, (x+self._outline_offset,y-self._outline_offset), draw=True, color = self._theme.display_outline_color)
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x+self._outline_offset,y-self._outline_offset), draw=True,
self._get_extent_and_render(line, footer, (x-self._outline_offset,y-self._outline_offset), draw=True, color = self._theme.display_outline_color)
color = self._theme.display_outline_color) self._get_extent_and_render(line, footer, (x-self._outline_offset,y-self._outline_offset), draw=True,
self._get_extent_and_render(line, footer,tlcorner=(x, y), draw=True) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,tlcorner=(x, y), draw=True)
y += h y += h
if linenum == 0: if linenum == 0:
self._first_line_right_extent = rightextent self._first_line_right_extent = rightextent
@ -395,7 +394,18 @@ class Renderer:
brcorner = (rightextent , y) brcorner = (rightextent , y)
return brcorner return brcorner
# xxx this is what to override for an SDL version def _set_theme_font(self):
self.footerFont = QtGui.QFont(self._theme.font_footer_name,
int(self._theme.font_footer_proportion), # size
QtGui.QFont.Normal, # weight
0)# italic
self.footerFont.setPixelSize(int(self._theme.font_footer_proportion))
self.mainFont = QtGui.QFont(self._theme.font_main_name,
int(self._theme.font_main_proportion), # size
QtGui.QFont.Normal, # weight
0)# italic
self.mainFont.setPixelSize(int(self._theme.font_main_proportion))
def _get_extent_and_render(self, line, footer, tlcorner=(0,0), draw=False, color=None): def _get_extent_and_render(self, line, footer, tlcorner=(0,0), draw=False, color=None):
""" """
Find bounding box of text - as render_single_line. Find bounding box of text - as render_single_line.
@ -403,23 +413,14 @@ class Renderer:
return width and height of text as a tuple (w,h) return width and height of text as a tuple (w,h)
""" """
# setup defaults # setup defaults
#log.debug(u'_get_extent_and_render %s %s %s ', [line], tlcorner, draw)
painter = QtGui.QPainter() painter = QtGui.QPainter()
painter.begin(self._frame) painter.begin(self._frame)
# 'twould be more efficient to set this once when theme changes # 'twould be more efficient to set this once when theme changes
# or p changes # or p changes
if footer : if footer :
font = QtGui.QFont(self._theme.font_footer_name, font = self.footerFont
int(self._theme.font_footer_proportion), # size
QtGui.QFont.Normal, # weight
0)# italic
font.setPixelSize(int(self._theme.font_footer_proportion))
else: else:
font = QtGui.QFont(self._theme.font_main_name, font = self.mainFont
int(self._theme.font_main_proportion), # size
QtGui.QFont.Normal, # weight
0)# italic
font.setPixelSize(int(self._theme.font_main_proportion))
painter.setFont(font) painter.setFont(font)
if color == None: if color == None:
if footer: if footer:
@ -429,7 +430,7 @@ class Renderer:
else: else:
painter.setPen(QtGui.QColor(color)) painter.setPen(QtGui.QColor(color))
x, y = tlcorner x, y = tlcorner
metrics=QtGui.QFontMetrics(font) metrics = QtGui.QFontMetrics(font)
# xxx some fudges to make it exactly like wx! Take 'em out later # xxx some fudges to make it exactly like wx! Take 'em out later
w = metrics.width(line) w = metrics.width(line)
h = metrics.height() - 2 h = metrics.height() - 2

View File

@ -70,6 +70,7 @@ class RenderManager:
""" """
Updates the render manager's information about the current screen. Updates the render manager's information about the current screen.
""" """
log.debug(u'Update Display')
if self.current_display != screen_number: if self.current_display != screen_number:
self.current_display = screen_number self.current_display = screen_number
self.calculate_default(self.screen_list[self.current_display]['size']) self.calculate_default(self.screen_list[self.current_display]['size'])
@ -100,7 +101,6 @@ class RenderManager:
self.theme = self.service_theme self.theme = self.service_theme
else: else:
self.theme = self.global_theme self.theme = self.global_theme
if self.theme is not self.renderer.theme_name: if self.theme is not self.renderer.theme_name:
log.debug(u'theme is now %s', self.theme) log.debug(u'theme is now %s', self.theme)
self.themedata = self.theme_manager.getThemeData(self.theme) self.themedata = self.theme_manager.getThemeData(self.theme)
@ -112,19 +112,16 @@ class RenderManager:
log.debug(u'build_text_rectangle ') log.debug(u'build_text_rectangle ')
main_rect = None main_rect = None
footer_rect = None footer_rect = None
if theme.font_main_override == False: if theme.font_main_override == False:
main_rect = QtCore.QRect(10,0, self.width-1, self.height-1) main_rect = QtCore.QRect(10,0, self.width-1, self.height-1)
else: else:
main_rect = QtCore.QRect(int(theme.font_main_x) , int(theme.font_main_y), main_rect = QtCore.QRect(int(theme.font_main_x) , int(theme.font_main_y),
int(theme.font_main_width)-1, int(theme.font_main_height)-1) int(theme.font_main_width)-1, int(theme.font_main_height)-1)
if theme.font_footer_override == False: if theme.font_footer_override == False:
footer_rect = QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start) footer_rect = QtCore.QRect(10,self.footer_start, self.width-1, self.height-self.footer_start)
else: else:
footer_rect = QtCore.QRect(int(theme.font_footer_x),int(theme.font_footer_y), footer_rect = QtCore.QRect(int(theme.font_footer_x),int(theme.font_footer_y),
int(theme.font_footer_width)-1, int(theme.font_footer_height)-1) int(theme.font_footer_width)-1, int(theme.font_footer_height)-1)
self.renderer.set_text_rectangle(main_rect,footer_rect) self.renderer.set_text_rectangle(main_rect,footer_rect)
def generate_preview(self, themedata): def generate_preview(self, themedata):
@ -132,9 +129,7 @@ class RenderManager:
self.calculate_default(QtCore.QSize(1024, 768)) self.calculate_default(QtCore.QSize(1024, 768))
self.renderer.set_theme(themedata) self.renderer.set_theme(themedata)
self.build_text_rectangle(themedata) self.build_text_rectangle(themedata)
self.renderer.set_frame_dest(self.width, self.height, True) self.renderer.set_frame_dest(self.width, self.height, True)
lines = [] lines = []
lines.append(u'Amazing Grace!') lines.append(u'Amazing Grace!')
lines.append(u'How sweet the sound') lines.append(u'How sweet the sound')
@ -165,15 +160,7 @@ class RenderManager:
log.debug(u'calculate default %s' , screen) log.debug(u'calculate default %s' , screen)
self.width = screen.width() self.width = screen.width()
self.height = screen.height() self.height = screen.height()
self.width = 1024
self.height = 768
log.debug(u'calculate default %d,%d' , self.width, self.height) log.debug(u'calculate default %d,%d' , self.width, self.height)
self.footer_start = int(self.height*0.90) # 90% is start of footer self.footer_start = int(self.height*0.90) # 90% is start of footer
def snoop_Image(self, image, image2=None):
"""
Debugging method to allow images to be viewed
"""
im = image.toImage()
im.save("renderer.png", "png")
if image2 is not None:
im = image2.toImage()
im.save("renderer2.png", "png")

View File

@ -66,6 +66,7 @@ class ServiceItem():
else: else:
self.RenderManager.set_override_theme(self.theme) self.RenderManager.set_override_theme(self.theme)
log.debug(u'Formatting slides') log.debug(u'Formatting slides')
self.frames = []
if self.service_item_type == u'text': if self.service_item_type == u'text':
for slide in self.service_frames: for slide in self.service_frames:
formated = self.RenderManager.format_slide(slide[u'raw_slide']) formated = self.RenderManager.format_slide(slide[u'raw_slide'])

View File

@ -184,6 +184,11 @@ class ServiceManager(QtGui.QWidget):
self.service_theme = self.ThemeComboBox.currentText() self.service_theme = self.ThemeComboBox.currentText()
self.parent.RenderManager.set_service_theme(self.service_theme) self.parent.RenderManager.set_service_theme(self.service_theme)
self.config.set_config(u'theme service theme', self.service_theme) self.config.set_config(u'theme service theme', self.service_theme)
if len(self.serviceItems) > 0:
tempServiceItems = self.serviceItems
self.onNewService()
for item in tempServiceItems:
self.addServiceItem(item[u'data'])
def addServiceItem(self, item, expand=True): def addServiceItem(self, item, expand=True):
""" """

View File

@ -56,7 +56,7 @@ class SlideData(QtCore.QAbstractListModel):
frame1 = frame.scaled(QtCore.QSize(280, 210), QtCore.Qt.KeepAspectRatio, frame1 = frame.scaled(QtCore.QSize(280, 210), QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation) QtCore.Qt.SmoothTransformation)
self.items.insert(row, (frame1, framenumber)) self.items.insert(row, (frame1, framenumber))
log.info(u'Items: %s' % self.items) log.info(u'Item loaded')
self.endInsertRows() self.endInsertRows()
def removeRow(self, row): def removeRow(self, row):
@ -133,6 +133,8 @@ class SlideController(QtGui.QWidget):
self.ControllerLayout.setMargin(0) self.ControllerLayout.setMargin(0)
# Controller list view # Controller list view
self.PreviewListView = QtGui.QListView(self.Controller) self.PreviewListView = QtGui.QListView(self.Controller)
self.PreviewListView.setUniformItemSizes(True)
self.PreviewListView.setIconSize(QtCore.QSize(250, 190))
self.PreviewListData = SlideData() self.PreviewListData = SlideData()
self.PreviewListView.isLive = self.isLive self.PreviewListView.isLive = self.isLive
#self.PreviewListView.setFlow(1) #self.PreviewListView.setFlow(1)