Calculate page breaks more accurately, and other HTML/CSS tidies

bzr-revno: 1008
This commit is contained in:
Jonathan Corwin 2010-09-04 15:51:22 +01:00
commit 451e4fd563
4 changed files with 138 additions and 91 deletions

View File

@ -325,7 +325,8 @@ from settingstab import SettingsTab
from serviceitem import ServiceItem from serviceitem import ServiceItem
from serviceitem import ServiceItemType from serviceitem import ServiceItemType
from serviceitem import ItemCapabilities from serviceitem import ItemCapabilities
from htmlbuilder import build_html from htmlbuilder import build_html, build_lyrics_format_css, \
build_lyrics_outline_css
from toolbar import OpenLPToolbar from toolbar import OpenLPToolbar
from dockwidget import OpenLPDockWidget from dockwidget import OpenLPDockWidget
from theme import ThemeLevel, ThemeXML from theme import ThemeLevel, ThemeXML

View File

@ -266,14 +266,10 @@ def build_html(item, screen, alert, islive):
`islive` `islive`
Item is going live, rather than preview/theme building Item is going live, rather than preview/theme building
""" """
try:
webkitvers = float(QtWebKit.qWebKitVersion())
log.debug(u'Webkit version = %s' % webkitvers)
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
webkitvers = webkit_version()
if item.bg_frame: if item.bg_frame:
image = u'data:image/png;base64,%s' % image_to_byte(item.bg_frame) image = u'data:image/png;base64,%s' % image_to_byte(item.bg_frame)
else: else:
@ -289,6 +285,18 @@ def build_html(item, screen, alert, islive):
build_lyrics_html(item, webkitvers)) build_lyrics_html(item, webkitvers))
return html return html
def webkit_version():
"""
Return the Webkit version in use.
Note method added relatively recently, so return 0 if prior to this
"""
try:
webkitvers = float(QtWebKit.qWebKitVersion())
log.debug(u'Webkit version = %s' % webkitvers)
except AttributeError:
webkitvers = 0
return webkitvers
def build_background_css(item, width, height): def build_background_css(item, width, height):
""" """
Build the background css Build the background css
@ -306,24 +314,25 @@ def build_background_css(item, width, height):
else: else:
if theme.background_direction == u'horizontal': if theme.background_direction == u'horizontal':
background = \ background = \
u'background: -webkit-gradient(linear, left top, left bottom, ' \ u'background: ' \
u'-webkit-gradient(linear, left top, left bottom, ' \
'from(%s), to(%s))' % (theme.background_startColor, 'from(%s), to(%s))' % (theme.background_startColor,
theme.background_endColor) theme.background_endColor)
elif theme.background_direction == u'vertical': elif theme.background_direction == u'vertical':
background = \ background = \
u'background: -webkit-gradient(linear, left top, right top,' \ u'background: -webkit-gradient(linear, left top, ' \
'from(%s), to(%s))' % (theme.background_startColor, u'right top, from(%s), to(%s))' % \
theme.background_endColor) (theme.background_startColor, theme.background_endColor)
else: else:
background = \ background = \
u'background: -webkit-gradient(radial, %s 50%%, 100, %s 50%%, %s,' \ u'background: -webkit-gradient(radial, %s 50%%, 100, %s ' \
'from(%s), to(%s))' % (width, width, width, theme.background_startColor, u'50%%, %s, from(%s), to(%s))' % (width, width, width,
theme.background_endColor) theme.background_startColor, theme.background_endColor)
return background return background
def build_lyrics_css(item, webkitvers): def build_lyrics_css(item, webkitvers):
""" """
Build the video display css Build the lyrics display css
`item` `item`
Service Item containing theme and location information Service Item containing theme and location information
@ -363,24 +372,8 @@ def build_lyrics_css(item, webkitvers):
if theme: if theme:
lyricstable = u'left: %spx; top: %spx;' % \ lyricstable = u'left: %spx; top: %spx;' % \
(item.main.x(), item.main.y()) (item.main.x(), item.main.y())
if theme.display_horizontalAlign == 2: lyrics = build_lyrics_format_css(theme, item.main.width(),
align = u'center' item.main.height())
elif theme.display_horizontalAlign == 1:
align = u'right'
else:
align = u'left'
if theme.display_verticalAlign == 2:
valign = u'bottom'
elif theme.display_verticalAlign == 1:
valign = u'middle'
else:
valign = u'top'
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, # For performance reasons we want to show as few DIV's as possible,
# especially when animating/transitions. # especially when animating/transitions.
# However some bugs in older versions of qtwebkit mean we need to # However some bugs in older versions of qtwebkit mean we need to
@ -396,30 +389,89 @@ def build_lyrics_css(item, webkitvers):
# Before 534.4 the text-shadow didn't get displayed when # Before 534.4 the text-shadow didn't get displayed when
# webkit-text-stroke was used. So use an offset text layer underneath. # webkit-text-stroke was used. So use an offset text layer underneath.
# https://bugs.webkit.org/show_bug.cgi?id=19728 # https://bugs.webkit.org/show_bug.cgi?id=19728
if theme.display_outline: if webkitvers >= 533.3:
if webkitvers < 534.3: lyricsmain += build_lyrics_outline_css(theme)
lyrics += u' letter-spacing: 1px;' else:
outline = u' -webkit-text-stroke: %sem %s; ' \ outline = build_lyrics_outline_css(theme)
'-webkit-text-fill-color: %s; ' % \ if theme.display_shadow:
(float(theme.display_outline_size) / 16, if theme.display_outline and webkitvers < 534.3:
theme.display_outline_color, theme.font_main_color) shadow = u'padding-left: %spx; padding-top: %spx ' % \
if webkitvers >= 533.3: (theme.display_shadow_size, theme.display_shadow_size)
lyricsmain += outline shadow += build_lyrics_outline_css(theme, True)
if theme.display_shadow and webkitvers < 534.3: else:
shadow = u'-webkit-text-stroke: %sem %s; ' \ lyricsmain += u' text-shadow: %s %spx %spx;' % \
u'-webkit-text-fill-color: %s; ' \ (theme.display_shadow_color, theme.display_shadow_size,
u' padding-left: %spx; padding-top: %spx' % \ theme.display_shadow_size)
(float(theme.display_outline_size) / 16,
theme.display_shadow_color, theme.display_shadow_color,
theme.display_shadow_size, theme.display_shadow_size)
if theme.display_shadow and \
(not theme.display_outline or webkitvers >= 534.3):
lyricsmain += u' text-shadow: %s %spx %spx;' % \
(theme.display_shadow_color, theme.display_shadow_size,
theme.display_shadow_size)
lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow) lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow)
return lyrics_css return lyrics_css
def build_lyrics_outline_css(theme, is_shadow=False):
"""
Build the css which controls the theme outline
Also used by renderer for splitting verses
`theme`
Object containing theme information
`is_shadow`
If true, use the shadow colors instead
"""
if theme.display_outline:
size = float(theme.display_outline_size) / 16
if is_shadow:
fill_color = theme.display_shadow_color
outline_color = theme.display_shadow_color
else:
fill_color = theme.font_main_color
outline_color = theme.display_outline_color
return u' -webkit-text-stroke: %sem %s; ' \
u'-webkit-text-fill-color: %s; ' % (size, outline_color, fill_color)
else:
return u''
def build_lyrics_format_css(theme, width, height):
"""
Build the css which controls the theme format
Also used by renderer for splitting verses
`theme`
Object containing theme information
`width`
Width of the lyrics block
`height`
Height of the lyrics block
"""
if theme.display_horizontalAlign == 2:
align = u'center'
elif theme.display_horizontalAlign == 1:
align = u'right'
else:
align = u'left'
if theme.display_verticalAlign == 2:
valign = u'bottom'
elif theme.display_verticalAlign == 1:
valign = u'middle'
else:
valign = u'top'
lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \
'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; ' \
'margin:0; padding:0; width: %spx; height: %spx; ' % \
(align, valign, theme.font_main_name, theme.font_main_proportion,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
width, height)
if theme.display_outline:
if webkit_version() < 534.3:
lyrics += u' letter-spacing: 1px;'
if theme.font_main_italics:
lyrics += u' font-style:italic; '
if theme.font_main_weight == u'Bold':
lyrics += u' font-weight:bold; '
return lyrics
def build_lyrics_html(item, webkitvers): def build_lyrics_html(item, webkitvers):
""" """
Build the HTML required to show the lyrics Build the HTML required to show the lyrics

View File

@ -29,9 +29,10 @@ format it for the output display.
""" """
import logging import logging
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore, QtWebKit
from openlp.core.lib import resize_image, expand_tags from openlp.core.lib import resize_image, expand_tags, \
build_lyrics_format_css, build_lyrics_outline_css
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -142,42 +143,35 @@ class Renderer(object):
for verse in verses_text: for verse in verses_text:
lines = verse.split(u'\n') lines = verse.split(u'\n')
for line in lines: for line in lines:
text.append(line) text.append(line)
doc = QtGui.QTextDocument() web = QtWebKit.QWebView()
doc.setPageSize(QtCore.QSizeF(self._rect.width(), self._rect.height())) web.resize(self._rect.width(), self._rect.height())
df = doc.defaultFont() web.setVisible(False)
df.setPointSize(self._theme.font_main_proportion) frame = web.page().mainFrame()
df.setFamily(self._theme.font_main_name) # Adjust width and height to account for shadow. outline done in css
main_weight = 50 width = self._rect.width() - int(self._theme.display_shadow_size)
if self._theme.font_main_weight == u'Bold': height = self._rect.height() - int(self._theme.display_shadow_size)
main_weight = 75 shell = u'<html><head><style>#main {%s %s}</style><body>' \
df.setWeight(main_weight) u'<div id="main">' % \
doc.setDefaultFont(df) (build_lyrics_format_css(self._theme, width, height),
layout = doc.documentLayout() build_lyrics_outline_css(self._theme))
formatted = [] formatted = []
if self._theme.font_main_weight == u'Bold' and \ html_text = u''
self._theme.font_main_italics: styled_text = u''
shell = u'{p}{st}{it}%s{/it}{/st}{/p}' js_height = 'document.getElementById("main").scrollHeight'
elif self._theme.font_main_weight == u'Bold' and \
not self._theme.font_main_italics:
shell = u'{p}{st}%s{/st}{/p}'
elif self._theme.font_main_italics:
shell = u'{p}{it}%s{/it}{/p}'
else:
shell = u'{p}%s{/p}'
temp_text = u''
old_html_text = u''
for line in text: for line in text:
# mark line ends styled_line = expand_tags(line) + line_end
temp_text = temp_text + line + line_end styled_text += styled_line
html_text = shell % expand_tags(temp_text) html = shell + styled_text + u'</div></body></html>'
doc.setHtml(html_text) web.setHtml(html)
# Text too long so gone to next mage # Text too long so go to next page
if layout.pageCount() != 1: text_height = int(frame.evaluateJavaScript(js_height).toString())
formatted.append(shell % old_html_text) if text_height > height:
temp_text = line + line_end formatted.append(html_text)
old_html_text = temp_text html_text = u''
formatted.append(shell % old_html_text) styled_text = styled_line
html_text += line + line_end
formatted.append(html_text)
log.debug(u'format_slide - End') log.debug(u'format_slide - End')
return formatted return formatted

View File

@ -160,9 +160,9 @@ class ServiceItem(object):
self.themedata = self.render_manager.renderer._theme self.themedata = self.render_manager.renderer._theme
for slide in self._raw_frames: for slide in self._raw_frames:
before = time.time() before = time.time()
formated = self.render_manager \ formatted = self.render_manager \
.format_slide(slide[u'raw_slide'], line_break) .format_slide(slide[u'raw_slide'], line_break)
for page in formated: for page in formatted:
self._display_frames.append( self._display_frames.append(
{u'title': clean_tags(page), {u'title': clean_tags(page),
u'text': clean_tags(page.rstrip()), u'text': clean_tags(page.rstrip()),