# -*- coding: utf-8 -*- # vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # # Copyright (c) 2008-2014 Raoul Snyman # # Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # # Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # # Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # # Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # # Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # # Frode Woldsund, Martin Zibricky # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # # Software Foundation; version 2 of the License. # # # # This program is distributed in the hope that it will be useful, but WITHOUT # # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # # more details. # # # # 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 Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### import logging from PyQt4 import QtWebKit from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, \ VerticalType, HorizontalType log = logging.getLogger(__name__) HTMLSRC = u""" OpenLP Display %s %s
""" def build_html(item, screen, islive, background, image=None, plugins=None): """ Build the full web paged structure for display ``item`` Service Item to be displayed ``screen`` Current display information ``islive`` Item is going live, rather than preview/theme building ``background`` Theme background image - bytes ``image`` Image media item - bytes ``plugins`` The List of available plugins """ width = screen[u'size'].width() height = screen[u'size'].height() theme = item.themedata webkitvers = webkit_version() # Image generated and poked in if background: bgimage_src = u'src="data:image/png;base64,%s"' % background elif item.bg_image_bytes: bgimage_src = u'src="data:image/png;base64,%s"' % item.bg_image_bytes else: bgimage_src = u'style="display:none;"' if image: image_src = u'src="data:image/png;base64,%s"' % image else: image_src = u'style="display:none;"' css_additions = u'' js_additions = u'' html_additions = u'' if plugins: for plugin in plugins: css_additions += plugin.getDisplayCss() js_additions += plugin.getDisplayJavaScript() html_additions += plugin.getDisplayHtml() html = HTMLSRC % (build_background_css(item, width, height), css_additions, build_footer_css(item, height), build_lyrics_css(item, webkitvers), u'true' if theme and theme.display_slide_transition and islive \ else u'false', js_additions, bgimage_src, image_src, html_additions, build_lyrics_html(item, webkitvers)) 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): """ Build the background css ``item`` Service Item containing theme and location information """ width = int(width) / 2 theme = item.themedata background = u'background-color: black' if theme: if theme.background_type == \ BackgroundType.to_string(BackgroundType.Transparent): background = u'' elif theme.background_type == \ BackgroundType.to_string(BackgroundType.Solid): background = u'background-color: %s' % theme.background_color else: if theme.background_direction == BackgroundGradientType.to_string \ (BackgroundGradientType.Horizontal): background = \ u'background: ' \ u'-webkit-gradient(linear, left top, left bottom, ' \ 'from(%s), to(%s)) fixed' % (theme.background_start_color, theme.background_end_color) elif theme.background_direction == \ BackgroundGradientType.to_string( \ BackgroundGradientType.LeftTop): background = \ u'background: ' \ u'-webkit-gradient(linear, left top, right bottom, ' \ 'from(%s), to(%s)) fixed' % (theme.background_start_color, theme.background_end_color) elif theme.background_direction == \ BackgroundGradientType.to_string \ (BackgroundGradientType.LeftBottom): background = \ u'background: ' \ u'-webkit-gradient(linear, left bottom, right top, ' \ 'from(%s), to(%s)) fixed' % (theme.background_start_color, theme.background_end_color) elif theme.background_direction == \ BackgroundGradientType.to_string \ (BackgroundGradientType.Vertical): background = \ u'background: -webkit-gradient(linear, left top, ' \ u'right top, from(%s), to(%s)) fixed' % \ (theme.background_start_color, theme.background_end_color) else: background = \ u'background: -webkit-gradient(radial, %s 50%%, 100, %s ' \ u'50%%, %s, from(%s), to(%s)) fixed' % (width, width, width, theme.background_start_color, theme.background_end_color) return background def build_lyrics_css(item, webkitvers): """ Build the lyrics display css ``item`` Service Item containing theme and location information ``webkitvers`` The version of qtwebkit we're using """ style = u""" .lyricstable { z-index: 5; position: absolute; display: table; %s } .lyricscell { display: table-cell; word-wrap: break-word; %s } .lyricsmain { %s } .lyricsoutline { %s } .lyricsshadow { %s } """ theme = item.themedata lyricstable = u'' lyrics = u'' lyricsmain = u'' outline = u'' shadow = u'' if theme and item.main: lyricstable = u'left: %spx; top: %spx;' % (item.main.x(), item.main.y()) lyrics = build_lyrics_format_css(theme, item.main.width(), item.main.height()) # 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. # # Up to 534.3 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 # # Up to 534.3 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 webkitvers >= 533.3: lyricsmain += build_lyrics_outline_css(theme) else: outline = build_lyrics_outline_css(theme) if theme.font_main_shadow: if theme.font_main_outline and webkitvers <= 534.3: shadow = u'padding-left: %spx; padding-top: %spx;' % \ (int(theme.font_main_shadow_size) + (int(theme.font_main_outline_size) * 2), theme.font_main_shadow_size) shadow += build_lyrics_outline_css(theme, True) else: lyricsmain += u' text-shadow: %s %spx %spx;' % \ (theme.font_main_shadow_color, theme.font_main_shadow_size, theme.font_main_shadow_size) lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow) 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.font_main_outline: size = float(theme.font_main_outline_size) / 16 if is_shadow: fill_color = theme.font_main_shadow_color outline_color = theme.font_main_shadow_color else: fill_color = theme.font_main_color outline_color = theme.font_main_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 """ align = HorizontalType.Names[theme.display_horizontal_align] valign = VerticalType.Names[theme.display_vertical_align] if theme.font_main_outline: left_margin = int(theme.font_main_outline_size) * 2 else: left_margin = 0 justify = u'white-space:pre-wrap;' # fix tag incompatibilities if theme.display_horizontal_align == HorizontalType.Justify: justify = u'' if theme.display_vertical_align == VerticalType.Bottom: padding_bottom = u'0.5em' else: padding_bottom = u'0' lyrics = u'%s 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; padding-bottom: %s; padding-left: %spx; width: %spx;' \ 'height: %spx; ' % \ (justify, align, valign, theme.font_main_name, theme.font_main_size, theme.font_main_color, 100 + int(theme.font_main_line_adjustment), padding_bottom, left_margin, width, height) if theme.font_main_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_bold: lyrics += u' font-weight:bold; ' return lyrics def build_lyrics_html(item, webkitvers): """ Build the HTML required to show the lyrics ``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.3 and theme and theme.font_main_outline: lyrics += u'
' \ u'
' if webkitvers < 533.3: lyrics += u'
' \ u'
' lyrics += u'
' \ u'
' return lyrics def build_footer_css(item, height): """ Build the display of the item footer ``item`` Service Item to be processed. """ style = u""" left: %spx; bottom: %spx; width: %spx; font-family: %s; font-size: %spt; color: %s; text-align: left; white-space: nowrap; """ theme = item.themedata if not theme or not item.footer: return u'' bottom = height - int(item.footer.y()) - int(item.footer.height()) lyrics_html = style % (item.footer.x(), bottom, item.footer.width(), theme.font_footer_name, theme.font_footer_size, theme.font_footer_color) return lyrics_html