make subtitle font styles skinnable
authorFraxinas <andreas.frisch@multimedia-labs.de>
Wed, 27 May 2009 21:45:01 +0000 (23:45 +0200)
committerFraxinas <andreas.frisch@multimedia-labs.de>
Wed, 27 May 2009 21:45:01 +0000 (23:45 +0200)
data/skin.xml
lib/gui/esubtitle.cpp
lib/gui/esubtitle.h
lib/python/enigma_python.i
skin.py
tests/enigma.py

index ca1e97d..1592330 100755 (executable)
                <font filename="ae_AlMateen.ttf" name="Replacement" scale="90" replacement="1" />
                <font filename="tuxtxt.ttf" name="Console" scale="100" />
        </fonts>
                <font filename="ae_AlMateen.ttf" name="Replacement" scale="90" replacement="1" />
                <font filename="tuxtxt.ttf" name="Console" scale="100" />
        </fonts>
+       <!-- Subtitle effects -->
+       <subtitles>
+               <sub name="Subtitle_TTX" font="Regular;30" shadowColor="#40101010" shadowOffset="3,3" />
+               <sub name="Subtitle_Regular" font="Regular;30" foregroundColor="#DCDCDC" shadowColor="#40101010" shadowOffset="3,3" />
+               <sub name="Subtitle_Bold" font="Replacement;30" foregroundColor="#DCDCDC" shadowColor="#40101010" shadowOffset="3,3" />
+               <sub name="Subtitle_Italic" font="Regular;30" foregroundColor="#DCAAAA" shadowColor="#40101010" shadowOffset="3,3" />
+               <!-- omitting foregroundColor attribute will enable auto-assignment of color -->
+       </subtitles>
        <!-- Main infobar -->
        <screen name="InfoBar" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent">
                <!-- Background -->
        <!-- Main infobar -->
        <screen name="InfoBar" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent">
                <!-- Background -->
index ca5c20d..376fa24 100644 (file)
@@ -10,6 +10,8 @@
                ....
        */      
 
                ....
        */      
 
+eSubtitleWidget::eSubtitleStyle eSubtitleWidget::subtitleStyles[Subtitle_MAX];
+
 eSubtitleWidget::eSubtitleWidget(eWidget *parent)
        : eWidget(parent), m_hide_subtitles_timer(eTimer::create(eApp))
 {
 eSubtitleWidget::eSubtitleWidget(eWidget *parent)
        : eWidget(parent), m_hide_subtitles_timer(eTimer::create(eApp))
 {
@@ -131,42 +133,42 @@ int eSubtitleWidget::event(int event, void *data, void *data2)
                else if (m_page_ok)
                {
                        int elements = m_page.m_elements.size();
                else if (m_page_ok)
                {
                        int elements = m_page.m_elements.size();
-                       ePtr<gFont> font = new gFont("Regular", 38);
-                       painter.setFont(font);
+                       painter.setFont(subtitleStyles[Subtitle_TTX].font);
                        for (int i=0; i<elements; ++i)
                        {
                                eDVBTeletextSubtitlePageElement &element = m_page.m_elements[i];
                                eRect &area = element.m_area;
                                eRect shadow = area;
                        for (int i=0; i<elements; ++i)
                        {
                                eDVBTeletextSubtitlePageElement &element = m_page.m_elements[i];
                                eRect &area = element.m_area;
                                eRect shadow = area;
-                               shadow.moveBy(3,3);
-                               painter.setForegroundColor(gRGB(0,0,0));
+                               shadow.moveBy(subtitleStyles[Subtitle_TTX].shadow_offset);
+                               painter.setForegroundColor(subtitleStyles[Subtitle_TTX].shadow_color);
                                painter.renderText(shadow, element.m_text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
                                painter.renderText(shadow, element.m_text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
-                               painter.setForegroundColor(element.m_color);
+                               if ( !subtitleStyles[Subtitle_TTX].have_foreground_color )
+                                       painter.setForegroundColor(element.m_color);
+                               else
+                                       painter.setForegroundColor(subtitleStyles[Subtitle_TTX].foreground_color);
                                painter.renderText(area, element.m_text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
                        }
                }
                else if (m_pango_page_ok)
                {
                        int elements = m_pango_page.m_elements.size();
                                painter.renderText(area, element.m_text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
                        }
                }
                else if (m_pango_page_ok)
                {
                        int elements = m_pango_page.m_elements.size();
-                       ePtr<gFont> font = new gFont("Regular", 38);
+                       subfont_t face;
+
                        for (int i=0; i<elements; ++i)
                        {
                        for (int i=0; i<elements; ++i)
                        {
+                               face = Subtitle_Regular;
                                ePangoSubtitlePageElement &element = m_pango_page.m_elements[i];
                                ePangoSubtitlePageElement &element = m_pango_page.m_elements[i];
-                               std::string text = element.m_pango_line;                                
+                               std::string text = element.m_pango_line;
                                std::string::size_type loc = text.find("<", 0 );
                                if ( loc != std::string::npos )
                                {
                                        switch (char(text.at(1)))
                                        {
                                        case 'i':
                                std::string::size_type loc = text.find("<", 0 );
                                if ( loc != std::string::npos )
                                {
                                        switch (char(text.at(1)))
                                        {
                                        case 'i':
-                                               eDebug("found italic");
-                                               font = new gFont("LCD", 40);
+                                               face = Subtitle_Italic;
                                                break;
                                        case 'b':
                                                break;
                                        case 'b':
-                                               eDebug("found bold");
-                                               font = new gFont("Replacement", 40);
-                                               break;
-                                       default:
+                                               face = Subtitle_Bold;
                                                break;
                                        }
                                        text = text.substr(3, text.length()-7);
                                                break;
                                        }
                                        text = text.substr(3, text.length()-7);
@@ -174,13 +176,16 @@ int eSubtitleWidget::event(int event, void *data, void *data2)
                                text = replace_all(text, "&apos;", "'");
                                text = replace_all(text, "&quot;", "\"");
                                text = replace_all(text, "&amp;", "&");
                                text = replace_all(text, "&apos;", "'");
                                text = replace_all(text, "&quot;", "\"");
                                text = replace_all(text, "&amp;", "&");
-                               painter.setFont(font);          
+                               painter.setFont(subtitleStyles[face].font);
                                eRect &area = element.m_area;
                                eRect shadow = area;
                                eRect &area = element.m_area;
                                eRect shadow = area;
-                               shadow.moveBy(3,3);
-                               painter.setForegroundColor(gRGB(0,0,0));
+                               shadow.moveBy(subtitleStyles[face].shadow_offset);
+                               painter.setForegroundColor(subtitleStyles[face].shadow_color);
                                painter.renderText(shadow, text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
                                painter.renderText(shadow, text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
-                               painter.setForegroundColor(element.m_color);
+                               if ( !subtitleStyles[face].have_foreground_color && element.m_have_color )
+                                       painter.setForegroundColor(element.m_color);
+                               else
+                                       painter.setForegroundColor(subtitleStyles[face].foreground_color);
                                painter.renderText(area, text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
                        }
                }
                                painter.renderText(area, text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER);
                        }
                }
@@ -195,3 +200,13 @@ int eSubtitleWidget::event(int event, void *data, void *data2)
                return eWidget::event(event, data, data2);
        }
 }
                return eWidget::event(event, data, data2);
        }
 }
+
+void eSubtitleWidget::setFontStyle(subfont_t face, gFont *font, int haveColor, const gRGB &col, const gRGB &shadowCol, const ePoint &shadowOffset)
+{
+       subtitleStyles[face].font = font;
+       subtitleStyles[face].have_foreground_color = haveColor;
+       subtitleStyles[face].foreground_color = col;
+       subtitleStyles[face].shadow_color = shadowCol;
+       subtitleStyles[face].shadow_offset = shadowOffset;
+}
+
index 0a780ca..d728777 100644 (file)
@@ -8,10 +8,15 @@
 struct ePangoSubtitlePageElement
 {
        gRGB m_color;
 struct ePangoSubtitlePageElement
 {
        gRGB m_color;
+       bool m_have_color;
        std::string m_pango_line;
        eRect m_area;
        ePangoSubtitlePageElement(const gRGB &color, const std::string &text)
        std::string m_pango_line;
        eRect m_area;
        ePangoSubtitlePageElement(const gRGB &color, const std::string &text)
-               : m_color(color), m_pango_line(text)
+               : m_color(color), m_pango_line(text), m_have_color(true)
+       {
+       }
+       ePangoSubtitlePageElement(const std::string &text)
+               : m_pango_line(text), m_have_color(false)
        {
        }
 };
        {
        }
 };
@@ -37,11 +42,22 @@ public:
        void setPage(const eDVBSubtitlePage &p);
        void setPage(const ePangoSubtitlePage &p);
        void clearPage();
        void setPage(const eDVBSubtitlePage &p);
        void setPage(const ePangoSubtitlePage &p);
        void clearPage();
-
        void setPixmap(ePtr<gPixmap> &pixmap, gRegion changed);
        void setPixmap(ePtr<gPixmap> &pixmap, gRegion changed);
+
+       typedef enum { Subtitle_TTX, Subtitle_Regular, Subtitle_Bold, Subtitle_Italic, Subtitle_MAX } subfont_t;
+       struct eSubtitleStyle
+       {
+               subfont_t face;
+               int have_foreground_color, have_shadow_color;
+               gRGB foreground_color, shadow_color;
+               ePoint shadow_offset;
+               ePtr<gFont> font;
+       };
+
+       static void setFontStyle(subfont_t face, gFont *font, int autoColor, const gRGB &col, const gRGB &shadowCol, const ePoint &shadowOffset);
+
 protected:
        int event(int event, void *data=0, void *data2=0);
 protected:
        int event(int event, void *data=0, void *data2=0);
-
 private:
        int m_page_ok;
        eDVBTeletextSubtitlePage m_page;
 private:
        int m_page_ok;
        eDVBTeletextSubtitlePage m_page;
@@ -56,6 +72,8 @@ private:
 
        gRegion m_visible_region;
 
 
        gRegion m_visible_region;
 
+       static eSubtitleStyle subtitleStyles[Subtitle_MAX];
+
        ePtr<gPixmap> m_pixmap;  // pixmap to paint on next evtPaint
 };
 
        ePtr<gPixmap> m_pixmap;  // pixmap to paint on next evtPaint
 };
 
index fe0e71e..2fec2ff 100644 (file)
@@ -69,6 +69,7 @@ is usually caused by not marking PSignals as immutable.
 #include <lib/python/connections.h>
 #include <lib/gui/elistbox.h>
 #include <lib/gui/elistboxcontent.h>
 #include <lib/python/connections.h>
 #include <lib/gui/elistbox.h>
 #include <lib/gui/elistboxcontent.h>
+#include <lib/gui/esubtitle.h>
 #include <lib/service/listboxservice.h>
 #include <lib/nav/pcore.h>
 #include <lib/actions/action.h>
 #include <lib/service/listboxservice.h>
 #include <lib/nav/pcore.h>
 #include <lib/actions/action.h>
@@ -183,6 +184,7 @@ typedef long time_t;
 %include <lib/gui/ewindowstyleskinned.h>
 %include <lib/gui/ewidgetanimation.h>
 %include <lib/gui/evideo.h>
 %include <lib/gui/ewindowstyleskinned.h>
 %include <lib/gui/ewidgetanimation.h>
 %include <lib/gui/evideo.h>
+%include <lib/gui/esubtitle.h>
 %include <lib/service/listboxservice.h>
 %include <lib/nav/pcore.h>
 %include <lib/actions/action.h>
 %include <lib/service/listboxservice.h>
 %include <lib/nav/pcore.h>
 %include <lib/actions/action.h>
diff --git a/skin.py b/skin.py
index a37716f..d44e503 100644 (file)
--- a/skin.py
+++ b/skin.py
@@ -6,7 +6,6 @@ from os import path
 profile("LOAD:enigma_skin")
 from enigma import eSize, ePoint, gFont, eWindow, eLabel, ePixmap, eWindowStyleManager, \
        addFont, gRGB, eWindowStyleSkinned
 profile("LOAD:enigma_skin")
 from enigma import eSize, ePoint, gFont, eWindow, eLabel, ePixmap, eWindowStyleManager, \
        addFont, gRGB, eWindowStyleSkinned
-
 from Components.config import ConfigSubsection, ConfigText, config
 from Components.Converter.Converter import Converter
 from Components.Sources.Source import Source, ObsoleteSource
 from Components.config import ConfigSubsection, ConfigText, config
 from Components.Converter.Converter import Converter
 from Components.Sources.Source import Source, ObsoleteSource
@@ -298,6 +297,28 @@ def loadSingleSkinData(desktop, skin, path_prefix):
                        addFont(resolved_font, name, scale, is_replacement)
                        #print "Font: ", resolved_font, name, scale, is_replacement
 
                        addFont(resolved_font, name, scale, is_replacement)
                        #print "Font: ", resolved_font, name, scale, is_replacement
 
+       for c in skin.findall("subtitles"):
+               from enigma import eWidget, eSubtitleWidget
+               scale = ((1,1),(1,1))
+               for substyle in c.findall("sub"):
+                       get_attr = substyle.attrib.get
+                       font = parseFont(get_attr("font"), scale)
+                       col = get_attr("foregroundColor")
+                       if col:
+                               foregroundColor = parseColor(col)
+                               haveColor = 1
+                       else:
+                               foregroundColor = gRGB(0xFFFFFF)
+                               haveColor = 0
+                       col = get_attr("shadowColor")
+                       if col:
+                               shadowColor = parseColor(col)
+                       else:
+                               shadowColor = gRGB(0)
+                       shadowOffset = parsePosition(get_attr("shadowOffset"), scale)
+                       face = eval("eSubtitleWidget.%s" % get_attr("name"))
+                       eSubtitleWidget.setFontStyle(face, font, haveColor, foregroundColor, shadowColor, shadowOffset)
+
        for windowstyle in skin.findall("windowstyle"):
                style = eWindowStyleSkinned()
                id = windowstyle.attrib.get("id")
        for windowstyle in skin.findall("windowstyle"):
                style = eWindowStyleSkinned()
                id = windowstyle.attrib.get("id")
@@ -333,12 +354,12 @@ def loadSingleSkinData(desktop, skin, path_prefix):
 
                for color in windowstyle.findall("color"):
                        get_attr = color.attrib.get
 
                for color in windowstyle.findall("color"):
                        get_attr = color.attrib.get
-                       type = get_attr("name")
+                       colorType = get_attr("name")
                        color = parseColor(get_attr("color"))
                        try:
                        color = parseColor(get_attr("color"))
                        try:
-                               style.setColor(eWindowStyleSkinned.__dict__["col" + type], color)
+                               style.setColor(eWindowStyleSkinned.__dict__["col" + colorType], color)
                        except:
                        except:
-                               raise SkinError("Unknown color %s" % (type))
+                               raise SkinError("Unknown color %s" % (colorType))
                                #pass
 
                        #print "  color:", type, color
                                #pass
 
                        #print "  color:", type, color
@@ -528,15 +549,15 @@ def readSkin(screen, skin, names, desktop):
 
                        #print "Found code:"
                        #print codeText
 
                        #print "Found code:"
                        #print codeText
-                       type = widget.attrib.get('type')
+                       widgetType = widget.attrib.get('type')
 
                        code = compile(codeText, "skin applet", "exec")
 
 
                        code = compile(codeText, "skin applet", "exec")
 
-                       if type == "onLayoutFinish":
+                       if widgetType == "onLayoutFinish":
                                screen.onLayoutFinish.append(code)
                                #print "onLayoutFinish = ", codeText
                        else:
                                screen.onLayoutFinish.append(code)
                                #print "onLayoutFinish = ", codeText
                        else:
-                               raise SkinError("applet type '%s' unknown!" % type)
+                               raise SkinError("applet type '%s' unknown!" % widgetType)
                                #print "applet type '%s' unknown!" % type
 
                        continue
                                #print "applet type '%s' unknown!" % type
 
                        continue
index 2bf2a59..e82aa49 100644 (file)
@@ -96,6 +96,7 @@ eWindowStyleSkinned = None
 eButton = None
 eListboxPythonStringContent = None
 eListbox = None
 eButton = None
 eListboxPythonStringContent = None
 eListbox = None
+eSubtitleWidget = None
 
 class eEPGCache:
        @classmethod
 
 class eEPGCache:
        @classmethod