#include #include #include #include #include #include #include #include #include #include #include std::map< eString,tWidgetCreator > eSkin::widget_creator; eSkin *eSkin::active; eNamedColor *eSkin::searchColor(const eString &name) { for (std::list::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::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::iterator i(newcolors); i != colors.end(); ++i) { eNamedColor &col=*i; int d; for (d=0; dmaxcolors) || colorused[d+s]) break; if (s==col.size) break; } if (d==maxcolors) continue; col.index=gColor(d); for (int s=0; sGetChild(); 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::iterator it = fontAlias.find(name); if (it != fontAlias.end()) continue; std::map::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 entry: no name"); continue; } const char *src=node->GetAttributeValue("src"); if (!src) { eDebug("image/img=\"%s\" no src given", name); continue; } std::map >::iterator it = images.find(name); if (it != images.end()) { // eDebug("Image with name %s already loaded, skip %s", name, src); continue; } ePtr 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::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 >::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::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::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 >::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=lenGetType(), "eskin")) { eDebug("not an eskin"); return -1; } return 0; } void eSkin::parseSkins() { for (ePtrList::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::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::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::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::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::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::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::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 &ptr, const eString& name) const { eString img; std::map::const_iterator i = imageAlias.find(name); if (i != imageAlias.end()) img = i->second; else img = name; std::map >::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::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::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::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(); }