5 #include <lib/gui/eskin.h>
6 #include <lib/gui/ewidget.h>
7 #include <lib/gdi/gfbdc.h>
8 #include <lib/gdi/glcddc.h>
9 #include <lib/gdi/epng.h>
10 #include <lib/base/eerror.h>
11 #include <lib/gdi/font.h>
12 #include <lib/base/eptrlist.h>
14 std::map< eString,tWidgetCreator > eSkin::widget_creator;
18 eNamedColor *eSkin::searchColor(const eString &name)
20 for (std::list<eNamedColor>::iterator i(colors.begin()); i != colors.end(); ++i)
22 if (!i->name.compare(name))
32 void eSkin::addWidgetCreator(const eString &name, tWidgetCreator creator)
34 widget_creator[name] = creator; // add this tWidgetCreator to map... if exist.. overwrite
37 void eSkin::removeWidgetCreator(const eString &name, tWidgetCreator creator)
39 widget_creator.erase(name);
42 int eSkin::parseColor(const eString &name, const char* color, gRGB &col)
47 if (sscanf(color+1, "%lx", &vcol)!=1)
49 eDebug("invalid color named \"%s\" (value: %s)", name.c_str(), color+1);
52 col.r=(vcol>>16)&0xFF;
55 col.a=(vcol>>24)&0xFF;
58 eNamedColor *n=searchColor(color);
61 eDebug("invalid color named \"%s\" (alias to: \"%s\")", name.c_str(), color);
69 int eSkin::parseColors(XMLTreeNode *xcolors)
73 std::list<eNamedColor>::iterator newcolors=colors.end();
75 for (node=xcolors->GetChild(); node; node=node->GetNext())
77 if (strcmp(node->GetType(), "color"))
79 eDebug("junk found in colorsection (%s)", node->GetType());
83 const char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"), *end=node->GetAttributeValue("end");
87 eDebug("no color/name specified");
94 const char *size=node->GetAttributeValue("size");
104 if ((col.size>1) && (!end))
106 eDebug("no end specified in \"%s\" but is gradient", name);
110 if (parseColor(name, color, col.value))
113 if (end && parseColor(name, end, col.end))
116 colors.push_back(col);
117 if (newcolors == colors.end())
121 for (std::list<eNamedColor>::iterator i(newcolors); i != colors.end(); ++i)
125 for (d=0; d<maxcolors; d+=col.size)
128 for (s=0; s<col.size; s++)
129 if ((d+s>maxcolors) || colorused[d+s])
137 for (int s=0; s<col.size; s++, d++)
142 int rdiff=-col.value.r+col.end.r;
143 int gdiff=-col.value.g+col.end.g;
144 int bdiff=-col.value.b+col.end.b;
145 int adiff=-col.value.a+col.end.a;
146 rdiff*=s; rdiff/=(col.size-1);
147 gdiff*=s; gdiff/=(col.size-1);
148 bdiff*=s; bdiff/=(col.size-1);
149 adiff*=s; adiff/=(col.size-1);
150 palette[d].r=col.value.r+rdiff;
151 palette[d].g=col.value.g+gdiff;
152 palette[d].b=col.value.b+bdiff;
153 palette[d].a=col.value.a+adiff;
155 palette[d]=col.value;
161 int eSkin::parseScheme(XMLTreeNode *xscheme)
164 for (node=xscheme->GetChild(); node; node=node->GetNext())
166 if (strcmp(node->GetType(), "map"))
168 eDebug("illegal scheme entry found: %s", node->GetType());
171 char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color");
174 eDebug("no name or color specified in colorscheme");
179 if ((p=base.find('+'))!=-1)
181 offset=atoi(base.mid(p).c_str());
184 eNamedColor *n=searchColor(base);
187 eDebug("illegal color \"%s\" specified", base.c_str());
190 scheme[name] = gColor(n->index+offset);
195 int eSkin::parseFontAlias(XMLTreeNode *xscheme)
198 for (node=xscheme->GetChild(); node; node=node->GetNext())
200 if (strcmp(node->GetType(), "map"))
202 eDebug("illegal fontalias entry found: %s", node->GetType());
205 char *font=node->GetAttributeValue("font"),
206 *name=node->GetAttributeValue("name"),
207 *size=node->GetAttributeValue("size");
209 if (!name || !font || !size)
211 eDebug("no name, alias or size spezified in fontaliase");
215 std::map<eString, gFont>::iterator it = fontAlias.find(name);
216 if (it != fontAlias.end())
219 std::map<eString, eString>::iterator i = fonts.find(font);
220 if (i == fonts.end())
222 eDebug("font %s not found, skip make alias %s", font, name);
225 fontAlias[name]=gFont(i->second, atoi(size));
230 int eSkin::parseImages(XMLTreeNode *inode)
232 char *abasepath=inode->GetAttributeValue("basepath");
235 eString basepath=eString("/enigma/pictures/");
236 if (abasepath[0] == '/') // allow absolute paths
239 if (basepath[basepath.length()-1]!='/')
242 for (XMLTreeNode *node=inode->GetChild(); node; node=node->GetNext())
244 if (strcmp(node->GetType(), "img"))
246 eDebug("illegal image entry found: %s", node->GetType());
249 const char *name=node->GetAttributeValue("name");
252 eDebug("illegal <img> entry: no name");
255 const char *src=node->GetAttributeValue("src");
258 eDebug("image/img=\"%s\" no src given", name);
261 std::map<eString, ePtr<gPixmap> >::iterator it = images.find(name);
262 if (it != images.end())
264 // eDebug("Image with name %s already loaded, skip %s", name, src);
267 ePtr<gPixmap> image=0;
268 eString filename=basepath + eString(src);
269 if (abasepath[0] != '/')
271 // search first in CONFIGDIR
272 image=loadPNG((eString(CONFIGDIR)+filename).c_str());
274 image=loadPNG((eString(DATADIR)+filename).c_str());
277 image=loadPNG(filename.c_str());
281 eDebug("image/img=\"%s\" - %s: file not found", name, filename.c_str());
285 if (paldummy && !node->GetAttributeValue("nomerge"))
287 gPixmapDC mydc(image);
289 p.mergePalette(paldummy);
291 images[name] = image;
296 int eSkin::parseImageAlias(XMLTreeNode *xvalues)
298 for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext())
300 if (strcmp(node->GetType(), "map"))
302 eDebug("illegal values entry %s", node->GetType());
305 const char *name=node->GetAttributeValue("name"),
306 *img=node->GetAttributeValue("img");
309 eDebug("map entry has no name or img");
312 std::map<eString, eString>::iterator it = imageAlias.find(name);
313 if (it != imageAlias.end())
315 eDebug("imagealias %s does exist, skip make alias for image %s", name, img);
318 std::map<eString, ePtr<gPixmap> >::iterator i = images.find(img);
319 if (i == images.end())
321 eDebug("image %s not found, skip make alias %s", img , name);
324 imageAlias[name]=img;
329 int eSkin::parseFonts(XMLTreeNode *xfonts)
331 const char *abasepath=xfonts->GetAttributeValue("basepath");
332 eString basepath=abasepath?abasepath:FONTDIR;
334 if (basepath.length())
335 if (basepath[basepath.length()-1]!='/')
338 for (XMLTreeNode *node=xfonts->GetChild(); node; node=node->GetNext())
340 if (strcmp(node->GetType(), "font"))
342 eDebug("illegal fonts entry %s", node->GetType());
345 const char *file=node->GetAttributeValue("file");
348 eDebug("fonts entry has no file");
351 const char *name=node->GetAttributeValue("name");
354 eDebug("fonts entry has no name use filename %s as name", file);
357 std::map<eString, eString>::iterator it = fonts.find(name);
358 const char *ascale=node->GetAttributeValue("scale");
364 if (it != fonts.end())
366 eDebug("Font with name %s already loaded, skip %s", name, file);
369 fonts[name]=fontRenderClass::getInstance()->AddFont(basepath+eString(file), name, scale);
370 if (node->GetAttributeValue("replacement"))
371 eTextPara::setReplacementFont(name);
376 int eSkin::parseValues(XMLTreeNode *xvalues)
378 for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext())
380 if (strcmp(node->GetType(), "value"))
382 eDebug("illegal values entry %s", node->GetType());
385 const char *name=node->GetAttributeValue("name");
388 eDebug("values entry has no name");
391 const char *value=node->GetAttributeValue("value");
394 eDebug("values entry has no value");
397 std::map<eString, int>::iterator it = values.find(name);
398 if (it != values.end())
400 eDebug("value %s does exist, skip make value %s=%i", name, value);
403 values[name]=atoi(value);
408 gDC *eSkin::getDCbyName(const char *name)
411 if (!strcmp(name, "fb"))
412 dc=gFBDC::getInstance();
414 else if (!strcmp(name, "lcd"))
415 dc=gLCDDC::getInstance();
420 int eSkin::build(eWidget *widget, XMLTreeNode *node)
422 // eDebug("building a %s", node->GetType());
423 /* if (widget->getType() != node->GetType())
426 for (XMLAttribute *attrib=node->GetAttributes(); attrib; attrib=attrib->GetNext())
428 // eDebug("setting %s := %s", attrib->GetName(), attrib->GetValue());
429 if (widget->setProperty(attrib->GetName(), attrib->GetValue()))
435 for (XMLTreeNode *c=node->GetChild(); c; c=c->GetNext())
439 const char *name=c->GetAttributeValue("name");
442 w=widget->search(name);
446 std::map< eString, tWidgetCreator >::iterator it = widget_creator.find(c->GetType());
448 if ( it == widget_creator.end() )
450 eWarning("widget class %s does not exist", c->GetType());
453 w = (it->second)(widget);
457 // eDebug("failed.");
462 if ((err=build(w, c)))
474 palette=new gRGB[maxcolors];
476 memset(palette, 0, sizeof(gRGB)*maxcolors);
477 paldummy=new gImage(eSize(1, 1), 8);
478 paldummy->clut.data=palette;
479 paldummy->clut.colors=maxcolors;
481 colorused=new int[maxcolors];
482 memset(colorused, 0, maxcolors*sizeof(int));
494 for (std::map<eString, ePtr<gPixmap> >::iterator it(images.begin()); it != images.end(); it++)
498 int eSkin::load(const char *filename)
500 eDebug("loading skin: %s", filename);
501 FILE *in=fopen(filename, "rt");
505 parsers.push_front(new XMLTreeParser("ISO-8859-1"));
506 XMLTreeParser &parser=*parsers.first();
512 unsigned int len=fread(buf, 1, sizeof(buf), in);
513 done=len<sizeof(buf);
514 if (!parser.Parse(buf, len, done))
516 eDebug("parse error: %s at line %d",
517 parser.ErrorString(parser.GetErrorCode()),
518 parser.GetCurrentLineNumber());
526 XMLTreeNode *root=parser.RootNode();
529 if (strcmp(root->GetType(), "eskin"))
531 eDebug("not an eskin");
538 void eSkin::parseSkins()
540 for (ePtrList<XMLTreeParser>::reverse_iterator it(parsers); it != parsers.rend(); it++)
542 XMLTreeNode *node=it->RootNode();
544 for (node=node->GetChild(); node; node=node->GetNext())
545 if (!strcmp(node->GetType(), "colors"))
549 for (ePtrList<XMLTreeParser>::reverse_iterator it(parsers); it != parsers.rend(); it++)
551 XMLTreeNode *node=it->RootNode();
553 for (node=node->GetChild(); node; node=node->GetNext())
554 if (!strcmp(node->GetType(), "colorscheme"))
558 for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++)
560 XMLTreeNode *node=it->RootNode();
562 for (node=node->GetChild(); node; node=node->GetNext())
563 if (!strcmp(node->GetType(), "fonts"))
567 for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++)
569 XMLTreeNode *node=it->RootNode();
571 for (node=node->GetChild(); node; node=node->GetNext())
572 if (!strcmp(node->GetType(), "fontalias"))
573 parseFontAlias(node);
576 for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++)
578 XMLTreeNode *node=it->RootNode();
580 for (node=node->GetChild(); node; node=node->GetNext())
581 if (!strcmp(node->GetType(), "images"))
586 for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++)
588 XMLTreeNode *node=it->RootNode();
590 for (node=node->GetChild(); node; node=node->GetNext())
591 if (!strcmp(node->GetType(), "imagealias"))
592 parseImageAlias(node);
596 for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++)
598 XMLTreeNode *node=it->RootNode();
600 for (node=node->GetChild(); node; node=node->GetNext())
601 if (!strcmp(node->GetType(), "values"))
607 int eSkin::build(eWidget *widget, const char *name)
609 for (parserList::iterator i(parsers.begin()); i!=parsers.end(); ++i)
611 XMLTreeNode *node=i->RootNode();
612 node=node->GetChild();
615 if (!strcmp(node->GetType(), "object"))
617 const char *oname=node->GetAttributeValue("name");
618 if (!std::strcmp(name, oname))
620 node=node->GetChild();
621 return build(widget, node);
624 node=node->GetNext();
627 eDebug("didn't found it");
631 void eSkin::setPalette(gPixmapDC *pal)
636 p.setPalette(palette, 0, 256);
640 eSkin *eSkin::getActive()
643 eFatal("no active skin");
647 void eSkin::makeActive()
652 gColor eSkin::queryScheme(const eString& name) const
656 if ((p=base.find('+'))!=-1)
658 offset=atoi(base.mid(p).c_str());
662 std::map<eString, gColor>::const_iterator it = scheme.find(base);
664 if (it != scheme.end())
665 return it->second + offset;
667 // eWarning("%s does not exist", name.c_str());
672 RESULT eSkin::queryImage(ePtr<gPixmap> &ptr, const eString& name) const
676 std::map<eString, eString>::const_iterator i = imageAlias.find(name);
678 if (i != imageAlias.end())
683 std::map<eString, ePtr<gPixmap> >::const_iterator it = images.find(img);
685 if (it != images.end())
691 int eSkin::queryValue(const eString& name, int d) const
693 std::map<eString, int>::const_iterator it = values.find(name);
695 if (it != values.end())
701 gColor eSkin::queryColor(const eString& name)
705 int numcol=strtol(name.c_str(), &end, 10);
708 return gColor(numcol);
712 if ((p=base.find('+'))!=-1)
714 offset=atoi(base.mid(p).c_str());
718 eNamedColor *col=searchColor(base);
722 return queryScheme(name);
724 return col->index + offset;
727 gFont eSkin::queryFont(const eString& name)
729 std::map<eString, gFont>::iterator it = fontAlias.find(name); // check if name is a font alias
731 if ( it != fontAlias.end() ) // font alias found
737 unsigned int sem = name.rfind(';'); // check if exist ';' in name
738 if (sem != eString::npos) // then exist
740 family=name.left(sem);
741 size = atoi( name.mid(sem+1).c_str() );
746 std::map<eString, eString>::iterator i = fonts.find(family); // check if family is a font name
747 if ( i != fonts.end() ) // font exist
748 return gFont(i->second, size);
750 for (i = fonts.begin() ; i != fonts.end(); i++) // as last check if family name is a complete font Face
751 if ( i->second == family)
752 return gFont(i->second, size);
754 eFatal("Font %s does not exist", name.c_str() ); // halt Programm now... Font does not exist