Fix {} colour substitutions and problems displaying first slide

bzr-revno: 1006
This commit is contained in:
Jonathan Corwin 2010-09-03 20:49:09 +01:00
commit 1275fdb35a
3 changed files with 195 additions and 165 deletions

View File

@ -39,40 +39,40 @@ log = logging.getLogger(__name__)
html_expands = [] html_expands = []
html_expands.append({u'desc':u'Red', u'start tag':u'{r}', \ html_expands.append({u'desc':u'Red', u'start tag':u'{r}', \
u'start html':u'<font color=red>', \ u'start html':u'<span style="-webkit-text-fill-color:red">', \
u'end tag':u'{/r}', u'end html':u'</font>', \ u'end tag':u'{/r}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Black', u'start tag':u'{b}', \ html_expands.append({u'desc':u'Black', u'start tag':u'{b}', \
u'start html':u'<font color=black>', \ u'start html':u'<span style="-webkit-text-fill-color:black">', \
u'end tag':u'{/b}', u'end html':u'</font>', \ u'end tag':u'{/b}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Blue', u'start tag':u'{bl}', \ html_expands.append({u'desc':u'Blue', u'start tag':u'{bl}', \
u'start html':u'<font color=blue>', \ u'start html':u'<span style="-webkit-text-fill-color:blue">', \
u'end tag':u'{/bl}', u'end html':u'</font>', \ u'end tag':u'{/bl}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Yellow', u'start tag':u'{y}', \ html_expands.append({u'desc':u'Yellow', u'start tag':u'{y}', \
u'start html':u'<font color=yellow>', \ u'start html':u'<span style="-webkit-text-fill-color:yellow">', \
u'end tag':u'{/y}', u'end html':u'</font>', \ u'end tag':u'{/y}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Green', u'start tag':u'{g}', \ html_expands.append({u'desc':u'Green', u'start tag':u'{g}', \
u'start html':u'<font color=green>', \ u'start html':u'<span style="-webkit-text-fill-color:green">', \
u'end tag':u'{/g}', u'end html':u'</font>', \ u'end tag':u'{/g}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Pink', u'start tag':u'{pk}', \ html_expands.append({u'desc':u'Pink', u'start tag':u'{pk}', \
u'start html':u'<font color=#CC33CC>', \ u'start html':u'<span style="-webkit-text-fill-color:#CC33CC">', \
u'end tag':u'{/pk}', u'end html':u'</font>', \ u'end tag':u'{/pk}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Orange', u'start tag':u'{o}', \ html_expands.append({u'desc':u'Orange', u'start tag':u'{o}', \
u'start html':u'<font color=#CC0033>', \ u'start html':u'<span style="-webkit-text-fill-color:#CC0033">', \
u'end tag':u'{/o}', u'end html':u'</font>', \ u'end tag':u'{/o}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Purple', u'start tag':u'{pp}', \ html_expands.append({u'desc':u'Purple', u'start tag':u'{pp}', \
u'start html':u'<font color=#9900FF>', \ u'start html':u'<span style="-webkit-text-fill-color:#9900FF">', \
u'end tag':u'{/pp}', u'end html':u'</font>', \ u'end tag':u'{/pp}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'White', u'start tag':u'{w}', \ html_expands.append({u'desc':u'White', u'start tag':u'{w}', \
u'start html':u'<font color=white>', \ u'start html':u'<span style="-webkit-text-fill-color:white">', \
u'end tag':u'{/w}', u'end html':u'</font>', \ u'end tag':u'{/w}', u'end html':u'</span>', \
u'protected':False}) u'protected':False})
html_expands.append({u'desc':u'Superscript', u'start tag':u'{su}', \ html_expands.append({u'desc':u'Superscript', u'start tag':u'{su}', \
u'start html':u'<sup>', \ u'start html':u'<sup>', \

View File

@ -24,6 +24,8 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtWebKit
from openlp.core.lib import image_to_byte from openlp.core.lib import image_to_byte
HTMLSRC = u""" HTMLSRC = u"""
@ -39,7 +41,7 @@ HTMLSRC = u"""
body { body {
background-color: black; background-color: black;
} }
.dim { .size {
position: absolute; position: absolute;
left: 0px; left: 0px;
top: 0px; top: 0px;
@ -51,6 +53,9 @@ body {
background-color: black; background-color: black;
display: none; display: none;
} }
#image {
z-index:1;
}
#video { #video {
z-index:2; z-index:2;
} }
@ -136,8 +141,12 @@ body {
} }
document.getElementById('black').style.display = black; document.getElementById('black').style.display = black;
document.getElementById('lyricsmain').style.visibility = lyrics; document.getElementById('lyricsmain').style.visibility = lyrics;
document.getElementById('lyricsoutline').style.visibility = lyrics; outline = document.getElementById('lyricsoutline')
document.getElementById('lyricsshadow').style.visibility = lyrics; if(outline!=null)
outline.style.visibility = lyrics;
shadow = document.getElementById('lyricsshadow')
if(shadow!=null)
shadow.style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics; document.getElementById('footer').style.visibility = lyrics;
var vid = document.getElementById('video'); var vid = document.getElementById('video');
if(vid.src != ''){ if(vid.src != ''){
@ -156,7 +165,7 @@ body {
return 0; return 0;
} }
if(position == ''){ if(position == ''){
position = window.getComputedStyle(text, '').verticalAlign; position = getComputedStyle(text, '').verticalAlign;
} }
switch(position) switch(position)
{ {
@ -181,111 +190,62 @@ body {
} }
function show_text(newtext){ function show_text(newtext){
var text1 = document.getElementById('lyricsmain');
var texto1 = document.getElementById('lyricsoutline');
var texts1 = document.getElementById('lyricsshadow');
if(!transition){
text1.innerHTML = newtext;
texto1.innerHTML = newtext;
texts1.innerHTML = newtext;
return;
}
var text2 = document.getElementById('lyricsmain2');
var texto2 = document.getElementById('lyricsoutline2');
var texts2 = document.getElementById('lyricsshadow2');
if((text2.style.opacity == '')||(parseFloat(text2.style.opacity) < 0.5))
{
text2.innerHTML = text1.innerHTML;
text2.style.opacity = text1.style.opacity;
texto2.innerHTML = text1.innerHTML;
texto2.style.opacity = text1.style.opacity;
texts2.innerHTML = text1.innerHTML;
texts2.style.opacity = text1.style.opacity;
}
text1.style.opacity = 0;
text1.innerHTML = newtext;
texto1.style.opacity = 0;
texto1.innerHTML = newtext;
texts1.style.opacity = 0;
texts1.innerHTML = newtext;
// For performance reasons, we'll not animate the shadow for now
texts2.style.opacity = 0;
if(timer != null) if(timer != null)
clearTimeout(timer); clearTimeout(timer);
timer = setTimeout('text_fade()', 50); text_fade('lyricsmain', newtext);
text_fade('lyricsoutline', newtext);
text_fade('lyricsshadow', newtext);
if(text_opacity()==1) return;
timer = setTimeout(function(){
show_text(newtext);
}, 100);
} }
function text_fade(){ function text_fade(id, newtext){
var text1 = document.getElementById('lyricsmain'); /*
var texto1 = document.getElementById('lyricsoutline'); Using -webkit-transition: opacity 1s linear; would have been preferred
var texts1 = document.getElementById('lyricsshadow'); but it isn't currently quick enough when animating multiple layers of
var text2 = document.getElementById('lyricsmain2'); large areas of large text. Therefore do it manually as best we can.
var texto2 = document.getElementById('lyricsoutline2'); Hopefully in the future we can revisit and do more interesting
var texts2 = document.getElementById('lyricsshadow2'); transitions using -webkit-transition and -webkit-transform.
if(parseFloat(text1.style.opacity) < 1){ However we need to ensure interrupted transitions (quickly change 2
text1.style.opacity = parseFloat(text1.style.opacity) + 0.1; slides) still looks pretty and is zippy.
texto1.style.opacity = parseFloat(texto1.style.opacity) + 0.1; */
// Don't animate shadow (performance) var text = document.getElementById(id);
//texts1.style.opacity = parseFloat(texts1.style.opacity) + 0.1; if(text==null) return;
if(!transition){
text.innerHTML = newtext;
return;
} }
if(parseFloat(text2.style.opacity) > 0){ if(newtext==text.innerHTML){
text2.style.opacity = parseFloat(text2.style.opacity) - 0.1; text.style.opacity = parseFloat(text.style.opacity) + 0.3;
texto2.style.opacity = parseFloat(texto2.style.opacity) - 0.1; if(text.style.opacity>0.7)
// Don't animate shadow (performance) text.style.opacity = 1;
//texts2.style.opacity = parseFloat(texts2.style.opacity) - 0.1;
}
if((parseFloat(text1.style.opacity) < 1) ||
(parseFloat(text2.style.opacity) > 0)){
t = setTimeout('text_fade()', 50);
} else { } else {
text1.style.opacity = 1; text.style.opacity = parseFloat(text.style.opacity) - 0.3;
texto1.style.opacity = 1; if(text.style.opacity<=0.1){
texts1.style.opacity = 1; text.innerHTML = newtext;
text2.style.opacity = 0; }
texto2.style.opacity = 0;
texts2.style.opacity = 0;
} }
} }
function text_opacity(){
var text = document.getElementById('lyricsmain');
return getComputedStyle(text, '').opacity;
}
function show_text_complete(){ function show_text_complete(){
return (document.getElementById('lyricsmain').style.opacity == 1); return (text_opacity()==1);
} }
</script> </script>
</head> </head>
<body> <body>
<!-- <img id="image" class="size" src="%s" />
Using tables, rather than div's to make use of the vertical-align style that <video id="video" class="size"></video>
doesn't work on div's. This avoids the need to do positioning manually which %s
could get messy when changing verses esp. with transitions
Would prefer to use a single table and make use of -webkit-text-fill-color
-webkit-text-stroke and text-shadow styles, but they have problems working/
co-operating in qwebkit. https://bugs.webkit.org/show_bug.cgi?id=43187
Therefore one table for text, one for outline and one for shadow.
-->
<table class="lyricstable lyricscommon">
<tr><td id="lyricsmain" class="lyrics"></td></tr>
</table>
<table class="lyricsoutlinetable lyricscommon">
<tr><td id="lyricsoutline" class="lyricsoutline lyrics"></td></tr>
</table>
<table class="lyricsshadowtable lyricscommon">
<tr><td id="lyricsshadow" class="lyricsshadow lyrics"></td></tr>
</table>
<table class="lyricstable lyricscommon">
<tr><td id="lyricsmain2" class="lyrics"></td></tr>
</table>
<table class="lyricsoutlinetable lyricscommon">
<tr><td id="lyricsoutline2" class="lyricsoutline lyrics"></td></tr>
</table>
<table class="lyricsshadowtable lyricscommon">
<tr><td id="lyricsshadow2" class="lyricsshadow lyrics"></td></tr>
</table>
<div id="alert" style="visibility:hidden;"></div>
<div id="footer" class="footer"></div> <div id="footer" class="footer"></div>
<video class="dim" id="video"></video> <div id="black" class="size"></div>
<div class="dim" id="black"></div> <div id="alert" style="visibility:hidden;"></div>
<img class="dim" id="image" src="%s" />
</body> </body>
</html> </html>
""" """
@ -300,7 +260,13 @@ def build_html(item, screen, alert, islive):
Current display information Current display information
`alert` `alert`
Alert display display information Alert display display information
`islive`
Item is going live, rather than preview/theme building
""" """
try:
webkitvers = float(QtWebKit.qWebKitVersion())
except AttributeError:
webkitvers = 0
width = screen[u'size'].width() width = screen[u'size'].width()
height = screen[u'size'].height() height = screen[u'size'].height()
theme = item.themedata theme = item.themedata
@ -309,83 +275,144 @@ def build_html(item, screen, alert, islive):
else: else:
image = u'' image = u''
html = HTMLSRC % (width, height, html = HTMLSRC % (width, height,
build_alert(alert, width), build_alert_css(alert, width),
build_footer(item), build_footer_css(item),
build_lyrics(item), build_lyrics_css(item, webkitvers),
u'true' if theme and theme.display_slideTransition and islive \ u'true' if theme and theme.display_slideTransition and islive \
else u'false', else u'false',
image) image,
build_lyrics_html(item, webkitvers))
return html return html
def build_lyrics(item): def build_lyrics_css(item, webkitvers):
""" """
Build the video display div Build the video display css
`item` `item`
Service Item containing theme and location information Service Item containing theme and location information
`webkitvers`
The version of qtwebkit we're using
""" """
style = """ style = """
.lyricscommon { position: absolute; %s } .lyricstable {
.lyricstable { z-index:4; %s } z-index:4;
.lyricsoutlinetable { z-index:3; %s } position: absolute;
.lyricsshadowtable { z-index:2; %s } display: table;
.lyrics { %s } %s
.lyricsoutline { %s } }
.lyricsshadow { %s } .lyricscell {
display:table-cell;
word-wrap: break-word;
%s
}
.lyricsmain {
%s
}
.lyricsoutline {
%s
}
.lyricsshadow {
%s
}
""" """
theme = item.themedata theme = item.themedata
lyricscommon = u''
lyricstable = u'' lyricstable = u''
outlinetable = u''
shadowtable = u''
lyrics = u'' lyrics = u''
outline = u'display: none;' lyricsmain = u''
shadow = u'display: none;' outline = u''
shadow = u''
if theme: if theme:
lyricscommon = u'width: %spx; height: %spx; word-wrap: break-word; ' \
u'font-family: %s; font-size: %spt; color: %s; line-height: %d%%;' \
% (item.main.width(), item.main.height(), theme.font_main_name,
theme.font_main_proportion, theme.font_main_color,
100 + int(theme.font_main_line_adjustment))
lyricstable = u'left: %spx; top: %spx;' % \ lyricstable = u'left: %spx; top: %spx;' % \
(item.main.x(), item.main.y()) (item.main.x(), item.main.y())
outlinetable = u'left: %spx; top: %spx;' % \
(item.main.x(), item.main.y())
shadowtable = u'left: %spx; top: %spx;' % \
(item.main.x() + float(theme.display_shadow_size),
item.main.y() + float(theme.display_shadow_size))
align = u''
if theme.display_horizontalAlign == 2: if theme.display_horizontalAlign == 2:
align = u'text-align:center;' align = u'center'
elif theme.display_horizontalAlign == 1: elif theme.display_horizontalAlign == 1:
align = u'text-align:right;' align = u'right'
else: else:
align = u'text-align:left;' align = u'left'
if theme.display_verticalAlign == 2: if theme.display_verticalAlign == 2:
valign = u'vertical-align:bottom;' valign = u'bottom'
elif theme.display_verticalAlign == 1: elif theme.display_verticalAlign == 1:
valign = u'vertical-align:middle;' valign = u'middle'
else: else:
valign = u'vertical-align:top;' valign = u'top'
lyrics = u'%s %s' % (align, valign) lyrics = u'width: %spx; height: %spx; text-align: %s; ' \
'vertical-align: %s; font-family: %s; font-size: %spt; ' \
'color: %s; line-height: %d%%;' % \
(item.main.width(), item.main.height(), align, valign,
theme.font_main_name, theme.font_main_proportion,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment))
# For performance reasons we want to show as few DIV's as possible,
# especially when animating/transitions.
# However some bugs in older versions of qtwebkit mean we need to
# perform workarounds and add extra divs. Only do these when needed.
#
# Before 533.3 the webkit-text-fill colour wasn't displayed, only the
# stroke (outline) color. So put stroke layer underneath the main text.
#
# Before 534.4 the webkit-text-stroke was sometimes out of alignment
# with the fill, or normal text. letter-spacing=1 is workaround
# https://bugs.webkit.org/show_bug.cgi?id=44403
#
# Before 534.4 the text-shadow didn't get displayed when
# webkit-text-stroke was used. So use an offset text layer underneath.
# https://bugs.webkit.org/show_bug.cgi?id=19728
if theme.display_outline: if theme.display_outline:
lyricscommon += u' letter-spacing: 1px;' if webkitvers < 534.3:
outline = u'-webkit-text-stroke: %sem %s; ' % \ lyrics += u' letter-spacing: 1px;'
outline = u' -webkit-text-stroke: %sem %s; ' \
'-webkit-text-fill-color: %s; ' % \
(float(theme.display_outline_size) / 16, (float(theme.display_outline_size) / 16,
theme.display_outline_color) theme.display_outline_color, theme.font_main_color)
if theme.display_shadow: if webkitvers >= 533.3:
lyricsmain += outline
if theme.display_shadow and webkitvers < 534.3:
shadow = u'-webkit-text-stroke: %sem %s; ' \ shadow = u'-webkit-text-stroke: %sem %s; ' \
u'-webkit-text-fill-color: %s; ' % \ u'-webkit-text-fill-color: %s; ' \
u' padding-left: %spx; padding-top: %spx' % \
(float(theme.display_outline_size) / 16, (float(theme.display_outline_size) / 16,
theme.display_shadow_color, theme.display_shadow_color) theme.display_shadow_color, theme.display_shadow_color,
else: theme.display_shadow_size, theme.display_shadow_size)
if theme.display_shadow: if theme.display_shadow and \
shadow = u'color: %s;' % (theme.display_shadow_color) (not theme.display_outline or webkitvers >= 534.3):
lyrics_html = style % (lyricscommon, lyricstable, outlinetable, lyricsmain += u' text-shadow: %s %spx %spx;' % \
shadowtable, lyrics, outline, shadow) (theme.display_shadow_color, theme.display_shadow_size,
return lyrics_html theme.display_shadow_size)
lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow)
return lyrics_css
def build_lyrics_html(item, webkitvers):
"""
Build the HTML required to show the lyrics
def build_footer(item): `item`
Service Item containing theme and location information
`webkitvers`
The version of qtwebkit we're using
"""
# Bugs in some versions of QtWebKit mean we sometimes need additional
# divs for outline and shadow, since the CSS doesn't work.
# To support vertical alignment middle and bottom, nested div's using
# display:table/display:table-cell are required for each lyric block.
lyrics = u''
theme = item.themedata
if webkitvers < 534.4 and theme and theme.display_outline:
lyrics += u'<div class="lyricstable">' \
u'<div id="lyricsshadow" style="opacity:1" ' \
u'class="lyricscell lyricsshadow"></div></div>'
if webkitvers < 533.3:
lyrics += u'<div class="lyricstable">' \
u'<div id="lyricsoutline" style="opacity:1" ' \
u'class="lyricscell lyricsoutline"></div></div>'
lyrics += u'<div class="lyricstable">' \
u'<div id="lyricsmain" style="opacity:1" ' \
u'class="lyricscell lyricsmain"></div></div>'
return lyrics
def build_footer_css(item):
""" """
Build the display of the item footer Build the display of the item footer
@ -416,7 +443,7 @@ def build_footer(item):
theme.font_footer_proportion, theme.font_footer_color, align) theme.font_footer_proportion, theme.font_footer_color, align)
return lyrics_html return lyrics_html
def build_alert(alertTab, width): def build_alert_css(alertTab, width):
""" """
Build the display of the footer Build the display of the footer
@ -424,7 +451,7 @@ def build_alert(alertTab, width):
Details from the Alert tab for fonts etc Details from the Alert tab for fonts etc
""" """
style = """ style = """
width: %s; width: %spx;
vertical-align: %s; vertical-align: %s;
font-family: %s; font-family: %s;
font-size: %spt; font-size: %spt;

View File

@ -115,8 +115,11 @@ class MainDisplay(DisplayWidget):
self.screen = self.screens.current self.screen = self.screens.current
self.setVisible(False) self.setVisible(False)
self.setGeometry(self.screen[u'size']) self.setGeometry(self.screen[u'size'])
self.webView = QtWebKit.QWebView(self) self.scene = QtGui.QGraphicsScene()
self.webView.setGeometry(0, 0, self.screen[u'size'].width(), \ self.setScene(self.scene)
self.webView = QtWebKit.QGraphicsWebView()
self.scene.addItem(self.webView)
self.webView.resize(self.screen[u'size'].width(), \
self.screen[u'size'].height()) self.screen[u'size'].height())
self.page = self.webView.page() self.page = self.webView.page()
self.frame = self.page.mainFrame() self.frame = self.page.mainFrame()