diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2003-10-17 15:35:43 +0000 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2003-10-17 15:35:43 +0000 |
| commit | fc2f5b2cd655f1391f2abda1b39e37cdec98a951 (patch) | |
| tree | 312efcea86a319de407a7c314fb981fb1c71019a /lib/gui/eskin.cpp | |
| download | enigma2-fc2f5b2cd655f1391f2abda1b39e37cdec98a951.tar.gz enigma2-fc2f5b2cd655f1391f2abda1b39e37cdec98a951.zip | |
Initial revision
Diffstat (limited to 'lib/gui/eskin.cpp')
| -rw-r--r-- | lib/gui/eskin.cpp | 760 |
1 files changed, 760 insertions, 0 deletions
diff --git a/lib/gui/eskin.cpp b/lib/gui/eskin.cpp new file mode 100644 index 00000000..6cb98abd --- /dev/null +++ b/lib/gui/eskin.cpp @@ -0,0 +1,760 @@ +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> + +#include <lib/gui/eskin.h> +#include <lib/gui/ewidget.h> +#include <lib/gdi/gfbdc.h> +#include <lib/gdi/glcddc.h> +#include <lib/gdi/epng.h> +#include <lib/base/eerror.h> +#include <lib/gdi/font.h> +#include <lib/base/eptrlist.h> + +std::map< eString,tWidgetCreator > eSkin::widget_creator; + +eSkin *eSkin::active; + +eNamedColor *eSkin::searchColor(const eString &name) +{ + for (std::list<eNamedColor>::iterator i(colors.begin()); i != colors.end(); ++i) + { + if (!i->name.compare(name)) + return &*i; + } + return 0; +} + +void eSkin::clear() +{ +} + +void eSkin::addWidgetCreator(const eString &name, tWidgetCreator creator) +{ + widget_creator[name] = creator; // add this tWidgetCreator to map... if exist.. overwrite +} + +void eSkin::removeWidgetCreator(const eString &name, tWidgetCreator creator) +{ + widget_creator.erase(name); +} + +int eSkin::parseColor(const eString &name, const char* color, gRGB &col) +{ + if (color[0]=='#') + { + unsigned long vcol=0; + if (sscanf(color+1, "%lx", &vcol)!=1) + { + eDebug("invalid color named \"%s\" (value: %s)", name.c_str(), color+1); + return -1; + } + col.r=(vcol>>16)&0xFF; + col.g=(vcol>>8)&0xFF; + col.b=vcol&0xFF; + col.a=(vcol>>24)&0xFF; + } else + { + eNamedColor *n=searchColor(color); + if (!n) + { + eDebug("invalid color named \"%s\" (alias to: \"%s\")", name.c_str(), color); + return -1; + } + col=n->value; + } + return 0; +} + +int eSkin::parseColors(XMLTreeNode *xcolors) +{ + XMLTreeNode *node; + + std::list<eNamedColor>::iterator newcolors=colors.end(); + + for (node=xcolors->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "color")) + { + eDebug("junk found in colorsection (%s)", node->GetType()); + continue; + } + + const char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"), *end=node->GetAttributeValue("end"); + + if (!color || !name) + { + eDebug("no color/name specified"); + continue; + } + + eNamedColor col; + col.name=name; + + const char *size=node->GetAttributeValue("size"); + + if (size) + col.size=atoi(size); + else + col.size=0; + + if (!col.size) + col.size=1; + + if ((col.size>1) && (!end)) + { + eDebug("no end specified in \"%s\" but is gradient", name); + continue; + } + + if (parseColor(name, color, col.value)) + continue; + + if (end && parseColor(name, end, col.end)) + continue; + + colors.push_back(col); + if (newcolors == colors.end()) + --newcolors; + } + + for (std::list<eNamedColor>::iterator i(newcolors); i != colors.end(); ++i) + { + eNamedColor &col=*i; + int d; + for (d=0; d<maxcolors; d+=col.size) + { + int s; + for (s=0; s<col.size; s++) + if ((d+s>maxcolors) || colorused[d+s]) + break; + if (s==col.size) + break; + } + if (d==maxcolors) + continue; + col.index=gColor(d); + for (int s=0; s<col.size; s++, d++) + { + colorused[d]=1; + if (s) + { + int rdiff=-col.value.r+col.end.r; + int gdiff=-col.value.g+col.end.g; + int bdiff=-col.value.b+col.end.b; + int adiff=-col.value.a+col.end.a; + rdiff*=s; rdiff/=(col.size-1); + gdiff*=s; gdiff/=(col.size-1); + bdiff*=s; bdiff/=(col.size-1); + adiff*=s; adiff/=(col.size-1); + palette[d].r=col.value.r+rdiff; + palette[d].g=col.value.g+gdiff; + palette[d].b=col.value.b+bdiff; + palette[d].a=col.value.a+adiff; + } else + palette[d]=col.value; + } + } + return 0; +} + +int eSkin::parseScheme(XMLTreeNode *xscheme) +{ + XMLTreeNode *node; + for (node=xscheme->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal scheme entry found: %s", node->GetType()); + continue; + } + char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"); + if (!name || !color) + { + eDebug("no name or color specified in colorscheme"); + continue; + } + eString base=color; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + eNamedColor *n=searchColor(base); + if (!n) + { + eDebug("illegal color \"%s\" specified", base.c_str()); + continue; + } + scheme[name] = gColor(n->index+offset); + } + return 0; +} + +int eSkin::parseFontAlias(XMLTreeNode *xscheme) +{ + XMLTreeNode *node; + for (node=xscheme->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal fontalias entry found: %s", node->GetType()); + continue; + } + char *font=node->GetAttributeValue("font"), + *name=node->GetAttributeValue("name"), + *size=node->GetAttributeValue("size"); + + if (!name || !font || !size) + { + eDebug("no name, alias or size spezified in fontaliase"); + continue; + } + + std::map<eString, gFont>::iterator it = fontAlias.find(name); + if (it != fontAlias.end()) + continue; + + std::map<eString, eString>::iterator i = fonts.find(font); + if (i == fonts.end()) + { + eDebug("font %s not found, skip make alias %s", font, name); + continue; + } + fontAlias[name]=gFont(i->second, atoi(size)); + } + return 0; +} + +int eSkin::parseImages(XMLTreeNode *inode) +{ + char *abasepath=inode->GetAttributeValue("basepath"); + if (!abasepath) + abasepath=""; + eString basepath=eString("/enigma/pictures/"); + if (abasepath[0] == '/') // allow absolute paths + basepath=""; + basepath+=abasepath; + if (basepath[basepath.length()-1]!='/') + basepath+="/"; + + for (XMLTreeNode *node=inode->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "img")) + { + eDebug("illegal image entry found: %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("illegal <img> entry: no name"); + continue; + } + const char *src=node->GetAttributeValue("src"); + if (!src) + { + eDebug("image/img=\"%s\" no src given", name); + continue; + } + std::map<eString, ePtr<gPixmap> >::iterator it = images.find(name); + if (it != images.end()) + { +// eDebug("Image with name %s already loaded, skip %s", name, src); + continue; + } + ePtr<gPixmap> image=0; + eString filename=basepath + eString(src); + if (abasepath[0] != '/') + { + // search first in CONFIGDIR + image=loadPNG((eString(CONFIGDIR)+filename).c_str()); + if (!image) + image=loadPNG((eString(DATADIR)+filename).c_str()); + } + else // abs path + image=loadPNG(filename.c_str()); + + if (!image) + { + eDebug("image/img=\"%s\" - %s: file not found", name, filename.c_str()); + continue; + } + + if (paldummy && !node->GetAttributeValue("nomerge")) + { + gPixmapDC mydc(image); + gPainter p(mydc); + p.mergePalette(paldummy); + } + images[name] = image; + } + return 0; +} + +int eSkin::parseImageAlias(XMLTreeNode *xvalues) +{ + for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal values entry %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"), + *img=node->GetAttributeValue("img"); + if (!name || !img) + { + eDebug("map entry has no name or img"); + continue; + } + std::map<eString, eString>::iterator it = imageAlias.find(name); + if (it != imageAlias.end()) + { + eDebug("imagealias %s does exist, skip make alias for image %s", name, img); + continue; + } + std::map<eString, ePtr<gPixmap> >::iterator i = images.find(img); + if (i == images.end()) + { + eDebug("image %s not found, skip make alias %s", img , name); + continue; + } + imageAlias[name]=img; + } + return 0; +} + +int eSkin::parseFonts(XMLTreeNode *xfonts) +{ + const char *abasepath=xfonts->GetAttributeValue("basepath"); + eString basepath=abasepath?abasepath:FONTDIR; + + if (basepath.length()) + if (basepath[basepath.length()-1]!='/') + basepath+="/"; + + for (XMLTreeNode *node=xfonts->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "font")) + { + eDebug("illegal fonts entry %s", node->GetType()); + continue; + } + const char *file=node->GetAttributeValue("file"); + if (!file) + { + eDebug("fonts entry has no file"); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("fonts entry has no name use filename %s as name", file); + name = file; + } + std::map<eString, eString>::iterator it = fonts.find(name); + const char *ascale=node->GetAttributeValue("scale"); + int scale=0; + if (ascale) + scale=atoi(ascale); + if (!scale) + scale=100; + if (it != fonts.end()) + { + eDebug("Font with name %s already loaded, skip %s", name, file); + continue; + } + fonts[name]=fontRenderClass::getInstance()->AddFont(basepath+eString(file), name, scale); + if (node->GetAttributeValue("replacement")) + eTextPara::setReplacementFont(name); + } + return 0; +} + +int eSkin::parseValues(XMLTreeNode *xvalues) +{ + for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "value")) + { + eDebug("illegal values entry %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("values entry has no name"); + continue; + } + const char *value=node->GetAttributeValue("value"); + if (!value) + { + eDebug("values entry has no value"); + continue; + } + std::map<eString, int>::iterator it = values.find(name); + if (it != values.end()) + { + eDebug("value %s does exist, skip make value %s=%i", name, value); + continue; + } + values[name]=atoi(value); + } + return 0; +} + +gDC *eSkin::getDCbyName(const char *name) +{ + gPixmapDC *dc=0; + if (!strcmp(name, "fb")) + dc=gFBDC::getInstance(); +#ifndef DISABLE_LCD + else if (!strcmp(name, "lcd")) + dc=gLCDDC::getInstance(); +#endif + return dc; +} + +int eSkin::build(eWidget *widget, XMLTreeNode *node) +{ +// eDebug("building a %s", node->GetType()); +/* if (widget->getType() != node->GetType()) + return -1;*/ + + for (XMLAttribute *attrib=node->GetAttributes(); attrib; attrib=attrib->GetNext()) + { +// eDebug("setting %s := %s", attrib->GetName(), attrib->GetValue()); + if (widget->setProperty(attrib->GetName(), attrib->GetValue())) + { + eDebug("failed"); + return -1; + } + } + for (XMLTreeNode *c=node->GetChild(); c; c=c->GetNext()) + { + eWidget *w=0; + + const char *name=c->GetAttributeValue("name"); + + if (name) + w=widget->search(name); + + if (!w) + { + std::map< eString, tWidgetCreator >::iterator it = widget_creator.find(c->GetType()); + + if ( it == widget_creator.end() ) + { + eWarning("widget class %s does not exist", c->GetType()); + return -ENOENT; + } + w = (it->second)(widget); + } + if (!w) + { + // eDebug("failed."); + return -EINVAL; + } + w->zOrderRaise(); + int err; + if ((err=build(w, c))) + { + return err; + } + } + return 0; +} + +eSkin::eSkin() +{ + maxcolors=256; + + palette=new gRGB[maxcolors]; + + memset(palette, 0, sizeof(gRGB)*maxcolors); + paldummy=new gImage(eSize(1, 1), 8); + paldummy->clut.data=palette; + paldummy->clut.colors=maxcolors; + + colorused=new int[maxcolors]; + memset(colorused, 0, maxcolors*sizeof(int)); +} + +eSkin::~eSkin() +{ + if (active==this) + active=0; + + clear(); + + delete colorused; + + for (std::map<eString, ePtr<gPixmap> >::iterator it(images.begin()); it != images.end(); it++) + delete it->second; + + if (paldummy) + delete paldummy; +} + +int eSkin::load(const char *filename) +{ + eDebug("loading skin: %s", filename); + FILE *in=fopen(filename, "rt"); + if (!in) + return -1; + + parsers.push_front(new XMLTreeParser("ISO-8859-1")); + XMLTreeParser &parser=*parsers.first(); + char buf[2048]; + + int done; + do + { + unsigned int len=fread(buf, 1, sizeof(buf), in); + done=len<sizeof(buf); + if (!parser.Parse(buf, len, done)) + { + eDebug("parse error: %s at line %d", + parser.ErrorString(parser.GetErrorCode()), + parser.GetCurrentLineNumber()); + parsers.pop_front(); + fclose(in); + return -1; + } + } while (!done); + fclose(in); + + XMLTreeNode *root=parser.RootNode(); + if (!root) + return -1; + if (strcmp(root->GetType(), "eskin")) + { + eDebug("not an eskin"); + return -1; + } + + return 0; +} + +void eSkin::parseSkins() +{ + for (ePtrList<XMLTreeParser>::reverse_iterator it(parsers); it != parsers.rend(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "colors")) + parseColors(node); + } + + for (ePtrList<XMLTreeParser>::reverse_iterator it(parsers); it != parsers.rend(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "colorscheme")) + parseScheme(node); + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "fonts")) + parseFonts(node); + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "fontalias")) + parseFontAlias(node); + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "images")) + parseImages(node); + + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "imagealias")) + parseImageAlias(node); + + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "values")) + parseValues(node); + } +} + + +int eSkin::build(eWidget *widget, const char *name) +{ + for (parserList::iterator i(parsers.begin()); i!=parsers.end(); ++i) + { + XMLTreeNode *node=i->RootNode(); + node=node->GetChild(); + while (node) + { + if (!strcmp(node->GetType(), "object")) + { + const char *oname=node->GetAttributeValue("name"); + if (!std::strcmp(name, oname)) + { + node=node->GetChild(); + return build(widget, node); + } + } + node=node->GetNext(); + } + } + eDebug("didn't found it"); + return -ENOENT; +} + +void eSkin::setPalette(gPixmapDC *pal) +{ + if (palette) + { + gPainter p(*pal); + p.setPalette(palette, 0, 256); + } +} + +eSkin *eSkin::getActive() +{ + if (!active) + eFatal("no active skin"); + return active; +} + +void eSkin::makeActive() +{ + active=this; +} + +gColor eSkin::queryScheme(const eString& name) const +{ + eString base=name; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + + std::map<eString, gColor>::const_iterator it = scheme.find(base); + + if (it != scheme.end()) + return it->second + offset; + +// eWarning("%s does not exist", name.c_str()); + + return gColor(0); +} + +RESULT eSkin::queryImage(ePtr<gPixmap> &ptr, const eString& name) const +{ + eString img; + + std::map<eString, eString>::const_iterator i = imageAlias.find(name); + + if (i != imageAlias.end()) + img = i->second; + else + img = name; + + std::map<eString, ePtr<gPixmap> >::const_iterator it = images.find(img); + + if (it != images.end()) + ptr = it->second; + + return 0; +} + +int eSkin::queryValue(const eString& name, int d) const +{ + std::map<eString, int>::const_iterator it = values.find(name); + + if (it != values.end()) + return it->second; + + return d; +} + +gColor eSkin::queryColor(const eString& name) +{ + char *end; + + int numcol=strtol(name.c_str(), &end, 10); + + if (!*end) + return gColor(numcol); + + eString base=name; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + + eNamedColor *col=searchColor(base); + + if (!col) + { + return queryScheme(name); + } else + return col->index + offset; +} + +gFont eSkin::queryFont(const eString& name) +{ + std::map<eString, gFont>::iterator it = fontAlias.find(name); // check if name is a font alias + + if ( it != fontAlias.end() ) // font alias found + return it->second; + + eString family; + int size=0; + + unsigned int sem = name.rfind(';'); // check if exist ';' in name + if (sem != eString::npos) // then exist + { + family=name.left(sem); + size = atoi( name.mid(sem+1).c_str() ); + if (size<=0) + size=16; + } + + std::map<eString, eString>::iterator i = fonts.find(family); // check if family is a font name + if ( i != fonts.end() ) // font exist + return gFont(i->second, size); + + for (i = fonts.begin() ; i != fonts.end(); i++) // as last check if family name is a complete font Face + if ( i->second == family) + return gFont(i->second, size); + + eFatal("Font %s does not exist", name.c_str() ); // halt Programm now... Font does not exist + + return gFont(); +} |
