Update Render to use Qgradient instead of home built code.

Colors hard coded for now.
This commit is contained in:
Tim Bentley 2009-03-29 15:38:23 +01:00
parent 8aa67b5a8b
commit 4ac2ed4fd6
3 changed files with 67 additions and 61 deletions

View File

@ -17,13 +17,19 @@ You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA Place, Suite 330, Boston, MA 02111-1307 USA
""" """
import logging
import sys import sys
from PyQt4 import QtGui, QtCore, Qt from PyQt4 import QtGui, QtCore, Qt
from copy import copy from copy import copy
from interpolate import interpolate from interpolate import interpolate
class Renderer: class Renderer:
global log
log=logging.getLogger(u'Renderer')
log.info(u'Renderer Loaded')
"""All the functions for rendering a set of words onto a Device Context """All the functions for rendering a set of words onto a Device Context
How to use: How to use:
@ -54,7 +60,7 @@ class Renderer:
self.set_bg_image(theme.BackgroundParameter1) self.set_bg_image(theme.BackgroundParameter1)
def set_bg_image(self, filename): def set_bg_image(self, filename):
print "set bg image", filename log.debug(u"set bg image %s", filename)
self._bg_image_filename=filename self._bg_image_filename=filename
if self._paint is not None: if self._paint is not None:
self.scale_bg_image() self.scale_bg_image()
@ -67,7 +73,7 @@ class Renderer:
dcw=self._paint.width()+1;dch=self._paint.height() dcw=self._paint.width()+1;dch=self._paint.height()
imratio=imw/float(imh) imratio=imw/float(imh)
dcratio=dcw/float(dch) dcratio=dcw/float(dch)
print "Image scaling params", imw, imh, imratio, dcw, dch, dcratio log.debug(u"Image scaling params %s %s %s %s %s %s", imw, imh, imratio, dcw, dch, dcratio)
if imratio > dcratio: if imratio > dcratio:
scale=dcw/float(imw) scale=dcw/float(imw)
elif imratio < dcratio: elif imratio < dcratio:
@ -86,7 +92,7 @@ class Renderer:
self.scale_bg_image() self.scale_bg_image()
def set_words_openlp(self, words): def set_words_openlp(self, words):
# print "set words openlp", words # log.debug(u" "set words openlp", words
verses=[] verses=[]
words=words.replace("\r\n", "\n") words=words.replace("\r\n", "\n")
verses_text=words.split('\n\n') verses_text=words.split('\n\n')
@ -101,7 +107,7 @@ class Renderer:
return verses_text return verses_text
def render_screen(self, screennum): def render_screen(self, screennum):
print "render screen\n", screennum, self.words[screennum] log.debug(u"render screen\n %s %s ", screennum, self.words[screennum])
import time import time
t=0.0 t=0.0
words=self.words[screennum] words=self.words[screennum]
@ -113,48 +119,42 @@ class Renderer:
self._rect=rect self._rect=rect
def _render_background(self): def _render_background(self):
# xxx may have to prerender to a memdc when set theme is called for use on slow machines
# takes 26ms on mijiti's machine!
assert(self._theme) assert(self._theme)
assert(self._paint) assert(self._paint)
print "render background", self._theme.BackgroundType log.debug(u"render background %s %s", self._theme.BackgroundType)
p=QtGui.QPainter() p=QtGui.QPainter()
p.begin(self._paint) p.begin(self._paint)
if self._theme.BackgroundType == 0: if self._theme.BackgroundType == 0:
p.fillRect(self._paint.rect(), self._theme.BackgroundParameter1) p.fillRect(self._paint.rect(), self._theme.BackgroundParameter1)
elif self._theme.BackgroundType == 1: # gradient elif self._theme.BackgroundType == 1: # gradient
# xxx Use a QGradient Brush!!! #TODO Add Theme code and fix direction
# get colours as tuples
c1=self._theme.BackgroundParameter1.getRgb() gradient = QtGui.QLinearGradient(0, 0, self._paint.width(), self._paint.height())
c2=self._theme.BackgroundParameter2.getRgb() gradient.setColorAt(0, QtGui.QColor(255, 0, 0))
dir=self._theme.BackgroundParameter3 gradient.setColorAt(0.5, QtGui.QColor(0, 255, 0))
w=self._paint.width();h=self._paint.height() gradient.setColorAt(1, QtGui.QColor(0, 0, 255))
lines=[] p.setBrush(QtGui.QBrush(gradient))
pens=[] rectPath = QtGui.QPainterPath()
if dir == 0: # vertical
for y in range (h): MAX_X = self._paint.width()
c=interpolate(c1, c2, y/float(h)) MAX_Y = self._paint.height()
lines.append((0,y,w,y))
pens.append(QtGui.QPen(QtGui.QColor(c[0],c[1],c[2]))) # bleagh rectPath.moveTo(0, 0)
else: rectPath.lineTo(0, MAX_Y)
for x in range (w): rectPath.lineTo(MAX_X, MAX_Y)
c=interpolate(c1, c2, x/float(w)) rectPath.lineTo(MAX_X, 0)
lines.append((x,0,x,h)) rectPath.closeSubpath()
pens.append(QtGui.QPen(QtGui.QColor(c[0],c[1],c[2]))) # bleagh p.drawPath(rectPath)
for i in range(len(pens)):
p.setPen(pens[i])
l=lines[i]
p.drawLine(l[0],l[1],l[2],l[3]) # must be a better way!
elif self._theme.BackgroundType == 2: # image elif self._theme.BackgroundType == 2: # image
r=self._paint.rect() r=self._paint.rect()
print r.x(), r.y(), r.width(),r.height() log.debug(r.x(), r.y(), r.width(),r.height())
print self._theme.BackgroundParameter2 log.debug(self._theme.BackgroundParameter2)
if self._theme.BackgroundParameter2 is not None: if self._theme.BackgroundParameter2 is not None:
p.fillRect(self._paint.rect(), self._theme.BackgroundParameter2) p.fillRect(self._paint.rect(), self._theme.BackgroundParameter2)
p.drawPixmap(self.background_offsetx,self.background_offsety, self.img) p.drawPixmap(self.background_offsetx,self.background_offsety, self.img)
p.end() p.end()
print "render background done" log.debug(u"render background done")
def split_set_of_lines(self, lines): def split_set_of_lines(self, lines):
@ -166,7 +166,7 @@ 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
""" """
# print "Split set of lines" # log.debug(u" "Split set of lines"
# Probably ought to save the rendering results to a pseudoDC for redrawing efficiency. But let's not optimse prematurely! # Probably ought to save the rendering results to a pseudoDC for redrawing efficiency. But let's not optimse prematurely!
bboxes = [] bboxes = []
@ -202,7 +202,7 @@ class Renderer:
retval.append(thislines) retval.append(thislines)
thislines=[] thislines=[]
else: else:
# print "Just split where you can" # log.debug(u" "Just split where you can"
retval=[] retval=[]
startline=0 startline=0
endline=startline+1 endline=startline+1
@ -221,9 +221,10 @@ class Renderer:
def _render_lines(self, lines): def _render_lines(self, lines):
"""render a set of lines according to the theme, return bounding box""" """render a set of lines according to the theme, return bounding box"""
print "_render_lines", lines log.debug(u"_render_lines %s", lines)
bbox=self._render_lines_unaligned(lines) bbox=self._render_lines_unaligned(lines)
print bbox
t=self._theme t=self._theme
x=self._rect.left() x=self._rect.left()
@ -237,7 +238,7 @@ class Renderer:
assert(0, "Invalid value for theme.VerticalAlign:%d" % t.VerticalAlign) assert(0, "Invalid value for theme.VerticalAlign:%d" % t.VerticalAlign)
self._render_background() self._render_background()
bbox=self._render_lines_unaligned(lines, (x,y)) bbox=self._render_lines_unaligned(lines, (x,y))
print "render lines DONE" log.debug(u"render lines DONE")
return bbox return bbox
@ -249,7 +250,7 @@ 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"""
print "render unaligned", lines log.debug(u"render unaligned %s", lines)
x,y=tlcorner x,y=tlcorner
brx=x brx=x
bry=y bry=y
@ -268,7 +269,7 @@ class Renderer:
p.setPen(QtGui.QPen(QtGui.QColor(0,0,255))) p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
p.drawRect(retval) p.drawRect(retval)
p.end() p.end()
print "render unaligned DONE" log.debug(u"render unaligned DONE")
return retval return retval
@ -282,14 +283,14 @@ class Renderer:
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).
""" """
print "Render single line '%s' @ %s "%( line, tlcorner) 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
# right aligned with a "hanging indent" # right aligned with a "hanging indent"
# get the words # get the words
# print "Getting the words split right" # log.debug(u" "Getting the words split right"
words=line.split(" ") words=line.split(" ")
thisline=' '.join(words) thisline=' '.join(words)
lastword=len(words) lastword=len(words)
@ -307,8 +308,8 @@ class Renderer:
lastword-=1 lastword-=1
thisline=' '.join(words[:lastword]) thisline=' '.join(words[:lastword])
# print "This is how they split", lines # log.debug(u" "This is how they split", lines
# print "Now render them" # log.debug(u" "Now render them"
startx=x startx=x
starty=y starty=y
rightextent=None rightextent=None
@ -356,7 +357,7 @@ class Renderer:
self._get_extent_and_render(line, (x-self._outline_offset,y-self._outline_offset), dodraw=True, color = t.OutlineColor) self._get_extent_and_render(line, (x-self._outline_offset,y-self._outline_offset), dodraw=True, color = t.OutlineColor)
self._get_extent_and_render(line, tlcorner=(x,y), dodraw=True) self._get_extent_and_render(line, tlcorner=(x,y), dodraw=True)
# print "Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)"%( linenum, line, x, y,w,h) # log.debug(u" "Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)"%( linenum, line, x, y,w,h)
y += h y += h
if linenum == 0: if linenum == 0:
self._first_line_right_extent=rightextent self._first_line_right_extent=rightextent
@ -378,7 +379,7 @@ 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
print "_get_extent_and_render", [line], tlcorner, dodraw log.debug(u"_get_extent_and_render %s %s %s ", [line], tlcorner, dodraw)
p=QtGui.QPainter() p=QtGui.QPainter()
p.begin(self._paint) p.begin(self._paint)
# 'twould be more efficient to set this once when theme changes # 'twould be more efficient to set this once when theme changes
@ -390,10 +391,10 @@ class Renderer:
# to make the unit tests monitor independent, we have to be able to # to make the unit tests monitor independent, we have to be able to
# specify whether a font proportion is in pixels or points # specify whether a font proportion is in pixels or points
if self._theme.FontUnits.lower() == "pixels": if self._theme.FontUnits.lower() == "pixels":
print "pixels" log.debug(u"pixels")
font.setPixelSize(self._theme.FontProportion) font.setPixelSize(self._theme.FontProportion)
print self._theme.FontName, self._theme.FontProportion log.debug(self._theme.FontName, self._theme.FontProportion)
print font.family(), font.pointSize() log.debug(font.family(), font.pointSize())
p.setFont(font) p.setFont(font)
if color == None: if color == None:
p.setPen(self._theme.FontColor) p.setPen(self._theme.FontColor)

View File

@ -81,6 +81,7 @@ class TestRender_base:
def teardown_class(self): def teardown_class(self):
print "class quit", self, self.app print "class quit", self, self.app
self.app.quit() self.app.quit()
def setup_method(self, method): def setup_method(self, method):
print "SSsetup", method print "SSsetup", method
if not hasattr(self, "app"): if not hasattr(self, "app"):
@ -157,6 +158,7 @@ Line 3"""
expected_answer=["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"] expected_answer=["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"]
answer=self.r.set_words_openlp(words) answer=self.r.set_words_openlp(words)
assert (answer==expected_answer) assert (answer==expected_answer)
def test_render_screens(self): def test_render_screens(self):
words=""" words="""
Verse 1: Line 1 Verse 1: Line 1
@ -177,6 +179,7 @@ Line 3"""
answer=self.r.render_screen(v) answer=self.r.render_screen(v)
# print v, answer.x(), answer.y(), answer.width(), answer.height() # print v, answer.x(), answer.y(), answer.width(), answer.height()
assert(answer==expected_answer[v]) assert(answer==expected_answer[v])
def split_test(self, number, answer, expected_answers): def split_test(self, number, answer, expected_answers):
lines=[] lines=[]
print "Split test", number, answer print "Split test", number, answer

View File

@ -8,6 +8,8 @@ else:
from PyQt4 import QtGui from PyQt4 import QtGui
DelphiColors={"clRed":0xFF0000, DelphiColors={"clRed":0xFF0000,
"clBlue":0x0000FF,
"clYellow":0x0FFFF00,
"clBlack":0x000000, "clBlack":0x000000,
"clWhite":0xFFFFFF} "clWhite":0xFFFFFF}