From ab5aa90e1e05a89845c6e802ef1b2366d203aa45 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Wed, 30 Mar 2005 07:28:17 +0000 Subject: [PATCH] - default fonts handled in windowstyle - fixed 32bit ARGB support (drawLine) - add sdl (but currently disabled) - fixed /dev/vc/0 -> /dev/stdin for console input - added alignment to label - fixed skin parsing (getElementsByTagName didn't do what i expected) --- lib/driver/rcconsole.cpp | 2 +- lib/dvb/db.cpp | 1 + lib/gdi/Makefile.am | 2 +- lib/gdi/gfont.cpp | 3 ++ lib/gdi/gfont.h | 41 ++++++++++++++++++ lib/gdi/gpixmap.cpp | 31 +++++++++++--- lib/gdi/gpixmap.h | 34 --------------- lib/gdi/grc.cpp | 15 +++++-- lib/gdi/grc.h | 11 ++++- lib/gdi/sdl.cpp | 85 ++++++++++++++++++++++++++++++++++++++ lib/gdi/sdl.h | 27 ++++++++++++ lib/gui/ebutton.cpp | 3 ++ lib/gui/elabel.cpp | 51 +++++++++++++++++++++-- lib/gui/elabel.h | 20 ++++++++- lib/gui/ewidgetdesktop.cpp | 2 + lib/gui/ewindowstyle.cpp | 22 ++++++++++ lib/gui/ewindowstyle.h | 12 +++++- lib/python/enigma_python.i | 2 + skin.py | 63 +++++++++++++++++++++------- 19 files changed, 361 insertions(+), 66 deletions(-) create mode 100644 lib/gdi/gfont.cpp create mode 100644 lib/gdi/gfont.h create mode 100644 lib/gdi/sdl.cpp create mode 100644 lib/gdi/sdl.h diff --git a/lib/driver/rcconsole.cpp b/lib/driver/rcconsole.cpp index 3b5397b1..98ebed4f 100644 --- a/lib/driver/rcconsole.cpp +++ b/lib/driver/rcconsole.cpp @@ -112,7 +112,7 @@ class eRCConsoleInit eRCConsoleDriver driver; eRCConsole device; public: - eRCConsoleInit(): driver("/dev/vc/0"), device(&driver) + eRCConsoleInit(): driver("/dev/stdin"), device(&driver) { } }; diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index fb41df91..cdc05fcb 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -30,6 +30,7 @@ eDVBService &eDVBService::operator=(const eDVBService &s) RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) { name = m_service_name; + return 0; } int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query) diff --git a/lib/gdi/Makefile.am b/lib/gdi/Makefile.am index 419163c7..abb75b79 100644 --- a/lib/gdi/Makefile.am +++ b/lib/gdi/Makefile.am @@ -5,4 +5,4 @@ noinst_LIBRARIES = libenigma_gdi.a libenigma_gdi_a_SOURCES = \ region.cpp grc.cpp epng.cpp erect.cpp fb.cpp font.cpp font_arabic.cpp gfbdc.cpp \ - glcddc.cpp gpixmap.cpp lcd.cpp + glcddc.cpp gpixmap.cpp lcd.cpp sdl.cpp gfont.cpp diff --git a/lib/gdi/gfont.cpp b/lib/gdi/gfont.cpp new file mode 100644 index 00000000..14fc8f37 --- /dev/null +++ b/lib/gdi/gfont.cpp @@ -0,0 +1,3 @@ +#include + +DEFINE_REF(gFont); diff --git a/lib/gdi/gfont.h b/lib/gdi/gfont.h new file mode 100644 index 00000000..d6697ce0 --- /dev/null +++ b/lib/gdi/gfont.h @@ -0,0 +1,41 @@ +#ifndef __lib_gdi_gfont_h +#define __lib_gdi_gfont_h + +#include +#include + +/** + * \brief A softreference to a font. + * + * The font is specified by a name and a size. + * \c gFont is part of the \ref gdi. + */ +class gFont: public iObject +{ +DECLARE_REF(gFont); +public: + + std::string family; + int pointSize; + + /** + * \brief Constructs a font with the given name and size. + * \param family The name of the font, for example "NimbusSansL-Regular Sans L Regular". + * \param pointSize the size of the font in PIXELS. + */ + gFont(const std::string &family, int pointSize): + family(family), pointSize(pointSize) + { + } + + virtual ~gFont() + { + } + + gFont() + :pointSize(0) + { + } +}; + +#endif diff --git a/lib/gdi/gpixmap.cpp b/lib/gdi/gpixmap.cpp index 7b7b91a8..c2c75e7a 100644 --- a/lib/gdi/gpixmap.cpp +++ b/lib/gdi/gpixmap.cpp @@ -1,8 +1,6 @@ #include #include -DEFINE_REF(gFont); - gLookup::gLookup() :size(0), lookup(0) { @@ -107,7 +105,7 @@ void gPixmap::unlock() void gPixmap::fill(const gRegion ®ion, const gColor &color) { - int i; + unsigned int i; for (i=0; idata; + __u8 *srf8 = 0; + __u32 *srf32 = 0; int stride = surface->stride; if (clip.rects.empty()) return; + + __u32 col; + if (surface->bpp == 8) + { + srf8 = (__u8*)surface->data; + } else if (surface->bpp == 32) + { + srf32 = (__u32*)surface->data; + + if (surface->clut.data && color < surface->clut.colors) + col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b); + else + col=0x10101*color; + col^=0xFF000000; + } int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y(); int dx, dy, x, y, s1, s2, e, temp, swap, i; @@ -292,6 +306,7 @@ void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color) } else swap=0; e = 2*dy-dx; + int lasthit = 0; for(i=1; i<=dx; i++) { @@ -328,7 +343,11 @@ void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color) } while (!clip.rects[a].contains(x, y)); lasthit = a; } - srf[y * stride + x] = color; + + if (srf8) + srf8[y * stride + x] = color; + if (srf32) + srf32[y * stride/4 + x] = col; fail: while (e>=0) { diff --git a/lib/gdi/gpixmap.h b/lib/gdi/gpixmap.h index 396d92b7..e549787c 100644 --- a/lib/gdi/gpixmap.h +++ b/lib/gdi/gpixmap.h @@ -81,40 +81,6 @@ struct gLookup void build(int size, const gPalette &pal, const gRGB &start, const gRGB &end); }; -/** - * \brief A softreference to a font. - * - * The font is specified by a name and a size. - * \c gFont is part of the \ref gdi. - */ -class gFont: public iObject -{ -DECLARE_REF(gFont); -public: - - std::string family; - int pointSize; - - /** - * \brief Constructs a font with the given name and size. - * \param family The name of the font, for example "NimbusSansL-Regular Sans L Regular". - * \param pointSize the size of the font in PIXELS. - */ - gFont(const std::string &family, int pointSize): - family(family), pointSize(pointSize) - { - } - - virtual ~gFont() - { - } - - gFont() - :pointSize(0) - { - } -}; - struct gSurface { int type; diff --git a/lib/gdi/grc.cpp b/lib/gdi/grc.cpp index a63aef92..e7748967 100644 --- a/lib/gdi/grc.cpp +++ b/lib/gdi/grc.cpp @@ -302,6 +302,10 @@ void gPainter::clippop() void gPainter::flush() { + gOpcode o; + o.opcode = gOpcode::flush; + o.dc = m_dc.grabRef(); + m_rc->submit(o); } void gPainter::end() @@ -340,15 +344,16 @@ void gDC::exec(gOpcode *o) case gOpcode::renderText: { ePtr para = new eTextPara(o->parm.renderText->area); + int flags = o->parm.renderText->flags; assert(m_current_font); para->setFont(m_current_font); - para->renderString(o->parm.renderText->text, 0); + para->renderString(o->parm.renderText->text, (flags & gPainter::RT_WRAP) ? RS_WRAP : 0); - if (o->parm.renderText->flags & gPainter::RT_HALIGN_RIGHT) + if (flags & gPainter::RT_HALIGN_RIGHT) para->realign(eTextPara::dirRight); - else if (o->parm.renderText->flags & gPainter::RT_HALIGN_CENTER) + else if (flags & gPainter::RT_HALIGN_CENTER) para->realign(eTextPara::dirCenter); - else if (o->parm.renderText->flags & gPainter::RT_HALIGN_BLOCK) + else if (flags & gPainter::RT_HALIGN_BLOCK) para->realign(eTextPara::dirBlock); ePoint offset = m_current_offset; @@ -454,6 +459,8 @@ void gDC::exec(gOpcode *o) m_current_offset = o->parm.setOffset->value; delete o->parm.setOffset; break; + case gOpcode::flush: + break; default: eFatal("illegal opcode %d. expect memory leak!", o->opcode); } diff --git a/lib/gdi/grc.h b/lib/gdi/grc.h index f6829902..8de5dadf 100644 --- a/lib/gdi/grc.h +++ b/lib/gdi/grc.h @@ -17,6 +17,7 @@ #include #include #include +#include class eTextPara; @@ -44,6 +45,8 @@ struct gOpcode setClip, addClip, popClip, + flush, + end,shutdown } opcode; @@ -178,10 +181,16 @@ public: enum { // todo, make mask. you cannot align both right AND center AND block ;) + RT_HALIGN_LEFT = 0, /* default */ RT_HALIGN_RIGHT = 1, RT_HALIGN_CENTER = 2, RT_HALIGN_BLOCK = 4, - RT_VALIGN_CENTER = 8 + + RT_VALIGN_TOP = 0, /* default */ + RT_VALIGN_CENTER = 8, + RT_VALIGN_BOTTOM = 16, + + RT_WRAP = 32 }; void renderText(const eRect &position, const std::string &string, int flags=0); diff --git a/lib/gdi/sdl.cpp b/lib/gdi/sdl.cpp new file mode 100644 index 00000000..591487f4 --- /dev/null +++ b/lib/gdi/sdl.cpp @@ -0,0 +1,85 @@ +#include + +#include +#include + +#include + +gSDLDC *gSDLDC::m_instance; + +gSDLDC::gSDLDC() +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + eWarning("Could not initialize SDL: %s", SDL_GetError()); + return; + } + + m_screen = SDL_SetVideoMode(720, 576, 32, SDL_HWSURFACE); + if (!m_screen) + { + eWarning("Could not create SDL surface: %s", SDL_GetError()); + return; + } + + m_instance=this; + + m_surface.type = 0; + m_surface.x = m_screen->w; + m_surface.y = m_screen->h; + m_surface.bpp = m_screen->format->BitsPerPixel; + m_surface.bypp = m_screen->format->BytesPerPixel; + m_surface.stride = m_screen->pitch; + m_surface.data = m_screen->pixels; + m_surface.clut.colors=256; + m_surface.clut.data=new gRGB[m_surface.clut.colors]; + + m_pixmap = new gPixmap(&m_surface); + + memset(m_surface.clut.data, 0, sizeof(*m_surface.clut.data)*m_surface.clut.colors); +} + +gSDLDC::~gSDLDC() +{ + SDL_Quit(); + m_instance=0; +} + +void gSDLDC::setPalette() +{ + if (!m_surface.clut.data) + return; + +/* for (int i=0; i<256; ++i) + { + fb->CMAP()->red[i]=ramp[m_surface.clut.data[i].r]<<8; + fb->CMAP()->green[i]=ramp[m_surface.clut.data[i].g]<<8; + fb->CMAP()->blue[i]=ramp[m_surface.clut.data[i].b]<<8; + fb->CMAP()->transp[i]=rampalpha[m_surface.clut.data[i].a]<<8; + if (!fb->CMAP()->red[i]) + fb->CMAP()->red[i]=0x100; + } + fb->PutCMAP(); */ +} + +void gSDLDC::exec(gOpcode *o) +{ + switch (o->opcode) + { + case gOpcode::setPalette: + { + gDC::exec(o); + setPalette(); + break; + } + case gOpcode::flush: + SDL_Flip(m_screen); + eDebug("FLUSH"); + break; + default: + gDC::exec(o); + break; + } +} + +eAutoInitPtr init_gSDLDC(eAutoInitNumbers::graphic-1, "gSDLDC"); diff --git a/lib/gdi/sdl.h b/lib/gdi/sdl.h new file mode 100644 index 00000000..20ff04fa --- /dev/null +++ b/lib/gdi/sdl.h @@ -0,0 +1,27 @@ +#ifndef __lib_gdi_sdl_h +#define __lib_gdi_sdl_h + +#include "fb.h" +#include "gpixmap.h" +#include "grc.h" + +#include + +class gSDLDC: public gDC +{ + SDL_Surface *m_screen; + static gSDLDC *m_instance; + void exec(gOpcode *opcode); + + void setPalette(); + gSurface m_surface; +public: + + gSDLDC(); + virtual ~gSDLDC(); + static int getInstance(ePtr &ptr) { if (!m_instance) return -1; ptr = m_instance; return 0; } + int islocked() { return 0; } +}; + + +#endif diff --git a/lib/gui/ebutton.cpp b/lib/gui/ebutton.cpp index 06cfda07..30824df2 100644 --- a/lib/gui/ebutton.cpp +++ b/lib/gui/ebutton.cpp @@ -2,6 +2,9 @@ eButton::eButton(eWidget *parent): eLabel(parent) { + /* default to center alignment */ + m_valign = alignCenter; + m_halign = alignCenter; } void eButton::push() diff --git a/lib/gui/elabel.cpp b/lib/gui/elabel.cpp index 281a9d27..3519a7ac 100644 --- a/lib/gui/elabel.cpp +++ b/lib/gui/elabel.cpp @@ -2,7 +2,14 @@ eLabel::eLabel(eWidget *parent): eWidget(parent) { + ePtr style; + getStyle(style); + style->getFont(eWindowStyle::fontStatic, m_font); + + /* default to topleft alignment */ + m_valign = alignTop; + m_halign = alignLeft; } int eLabel::event(int event, void *data, void *data2) @@ -18,14 +25,34 @@ int eLabel::event(int event, void *data, void *data2) eWidget::event(event, data, data2); gPainter &painter = *(gPainter*)data2; - ePtr fnt = new gFont("Arial", 14); - painter.setFont(fnt); + painter.setFont(m_font); style->setStyle(painter, eWindowStyle::styleLabel); - painter.renderText(eRect(0, 0, size().width(), size().height()), m_text, gPainter::RT_HALIGN_CENTER|gPainter::RT_VALIGN_CENTER); + + int flags = 0; + if (m_valign == alignTop) + flags |= gPainter::RT_VALIGN_TOP; + else if (m_valign == alignCenter) + flags |= gPainter::RT_VALIGN_CENTER; + else if (m_valign == alignBottom) + flags |= gPainter::RT_VALIGN_BOTTOM; + + if (m_halign == alignLeft) + flags |= gPainter::RT_HALIGN_LEFT; + else if (m_halign == alignCenter) + flags |= gPainter::RT_HALIGN_CENTER; + else if (m_halign == alignRight) + flags |= gPainter::RT_HALIGN_RIGHT; + else if (m_halign == alignBlock) + flags |= gPainter::RT_HALIGN_BLOCK; + + flags |= gPainter::RT_WRAP; + painter.renderText(eRect(0, 0, size().width(), size().height()), m_text, flags); return 0; } + case evtChangedFont: case evtChangedText: + case evtChangedAlignment: invalidate(); return 0; default: @@ -40,3 +67,21 @@ void eLabel::setText(const std::string &string) m_text = string; event(evtChangedText); } + +void eLabel::setFont(gFont *font) +{ + m_font = font; + event(evtChangedFont); +} + +void eLabel::setVAlign(int align) +{ + m_valign = align; + event(evtChangedAlignment); +} + +void eLabel::setHAlign(int align) +{ + m_halign = align; + event(evtChangedAlignment); +} diff --git a/lib/gui/elabel.h b/lib/gui/elabel.h index b1f7c2cf..7e07f438 100644 --- a/lib/gui/elabel.h +++ b/lib/gui/elabel.h @@ -8,12 +8,30 @@ class eLabel: public eWidget public: eLabel(eWidget *parent); void setText(const std::string &string); + void setFont(gFont *font); + + enum + { + alignLeft, + alignTop=alignLeft, + alignCenter, + alignRight, + alignBottom=alignRight, + alignBlock + }; + + void setVAlign(int align); + void setHAlign(int align); protected: + ePtr m_font; + int m_valign, m_halign; int event(int event, void *data=0, void *data2=0); private: enum eLabelEvent { - evtChangedText = evtUserWidget + evtChangedText = evtUserWidget, + evtChangedFont, + evtChangedAlignment }; std::string m_text; }; diff --git a/lib/gui/ewidgetdesktop.cpp b/lib/gui/ewidgetdesktop.cpp index 1b5cf9b2..96f74636 100644 --- a/lib/gui/ewidgetdesktop.cpp +++ b/lib/gui/ewidgetdesktop.cpp @@ -82,6 +82,8 @@ void eWidgetDesktop::paint() painter.setBackgroundColor(m_background_color); painter.clear(); + painter.flush(); + m_dirty_region = gRegion(); } diff --git a/lib/gui/ewindowstyle.cpp b/lib/gui/ewindowstyle.cpp index 25b89460..a2e0efb2 100644 --- a/lib/gui/ewindowstyle.cpp +++ b/lib/gui/ewindowstyle.cpp @@ -110,6 +110,27 @@ void eWindowStyleSimple::drawFrame(gPainter &painter, const eRect &frame, int wh painter.line(frame.bottomLeft1(), frame.topLeft1()); } +RESULT eWindowStyleSimple::getFont(int what, ePtr &fnt) +{ + fnt = 0; + switch (what) + { + case fontStatic: + fnt = new gFont("Arial", 12); + break; + case fontButton: + fnt = new gFont("Arial", 20); + break; + case fontTitlebar: + fnt = new gFont("Arial", 25); + break; + default: + return -1; + } + return 0; +} + +#if 0 DEFINE_REF(eWindowStyleSkinned); eWindowStyleSkinned::eWindowStyleSkinned() @@ -140,3 +161,4 @@ void eWindowStyleSkinned::drawBorder(gPainter &painter, const eSize &size, const { } +#endif diff --git a/lib/gui/ewindowstyle.h b/lib/gui/ewindowstyle.h index 0014bfa4..f11d99de 100644 --- a/lib/gui/ewindowstyle.h +++ b/lib/gui/ewindowstyle.h @@ -27,8 +27,15 @@ public: frameButton, frameListboxEntry }; + + enum { + fontStatic, + fontButton, + fontTitlebar + }; + + virtual RESULT getFont(int what, ePtr &font) = 0; virtual ~eWindowStyle() = 0; - }; class eWindowStyleSimple: public eWindowStyle @@ -46,8 +53,10 @@ public: void paintBackground(gPainter &painter, const ePoint &offset, const eSize &size); void setStyle(gPainter &painter, int what); void drawFrame(gPainter &painter, const eRect &frame, int what); + RESULT getFont(int what, ePtr &font); }; +#if 0 class eWindowStyleSkinned: public eWindowStyle { DECLARE_REF(eWindowStyleSkinned); @@ -86,5 +95,6 @@ private: void drawBorder(gPainter &painter, const eSize &size, const struct borderSet &border, int where); }; +#endif #endif diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index 096254f9..59133cc5 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -58,6 +58,7 @@ is usually caused by not marking PSignals as immutable. #include #include #include +#include extern void runMainloop(); extern void quitMainloop(); @@ -106,6 +107,7 @@ extern PSignal1 &keyPressedSignal(); %include %include %include +%include /************** eptr **************/ diff --git a/skin.py b/skin.py index db4812ab..6ef8f939 100644 --- a/skin.py +++ b/skin.py @@ -14,7 +14,7 @@ dom = xml.dom.minidom.parseString( """ - + @@ -44,6 +44,12 @@ dom = xml.dom.minidom.parseString( """) +def elementsWithTag(el, tag): + for x in el: + if x.nodeType != xml.dom.minidom.Element.nodeType: + continue + if x.tagName == tag: + yield x def parsePosition(str): x, y = str.split(',') @@ -53,6 +59,10 @@ def parseSize(str): x, y = str.split(',') return eSize(int(x), int(y)) +def parseFont(str): + name, size = str.split(':') + return gFont(name, int(size)) + def applyAttributes(guiObject, node): # walk all attributes for p in range(node.attributes.length): @@ -65,33 +75,58 @@ def applyAttributes(guiObject, node): value = str(a.value) # and set attributes - if attrib == 'position': - guiObject.move(parsePosition(value)) - elif attrib == 'size': - guiObject.resize(parseSize(value)) - elif attrib == 'title': - guiObject.setTitle(value) - elif attrib != 'name': - print "unsupported attribute " + attrib + "=" + value + try: + if attrib == 'position': + guiObject.move(parsePosition(value)) + elif attrib == 'size': + guiObject.resize(parseSize(value)) + elif attrib == 'title': + guiObject.setTitle(value) + elif attrib == 'font': + guiObject.setFont(parseFont(value)) + elif attrib == "valign": + try: + guiObject.setVAlign( + { "top": guiObject.alignTop, + "center": guiObject.alignCenter, + "bottom": guiObject.alignBottom + }[value]) + except KeyError: + print "valign must be either top, center or bottom!" + elif attrib == "halign": + try: + guiObject.setHAlign( + { "left": guiObject.alignLeft, + "center": guiObject.alignCenter, + "right": guiObject.alignRight, + "block": guiObject.alignBlock + }[value]) + except KeyError: + print "halign must be either left, center, right or block!" + elif attrib != 'name': + print "unsupported attribute " + attrib + "=" + value + except AttributeError: + print "widget %s (%s) doesn't support attribute %s!" % ("", guiObject.__class__.__name__, attrib) def applyGUIskin(screen, parent, skin, name): myscreen = None # first, find the corresponding screen element - skin = dom.getElementsByTagName("skin")[0] - screens = skin.getElementsByTagName("screen") - del skin - for x in screens: + skin = dom.childNodes[0] + assert skin.tagName == "skin", "root element in skin must be 'skin'!" + + for x in elementsWithTag(skin.childNodes, "screen"): if x.getAttribute('name') == name: myscreen = x + del skin assert myscreen != None, "no skin for screen '" + name + "' found!" applyAttributes(parent, myscreen) # now walk all widgets - for widget in myscreen.getElementsByTagName("widget"): + for widget in elementsWithTag(myscreen.childNodes, "widget"): wname = widget.getAttribute('name') if wname == None: print "widget has no name!" -- 2.30.2