skinelem.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include <precomp.h>
  2. #include <api.h>
  3. #include "skinelem.h"
  4. #include <api/skin/skin.h>
  5. #include <api/skin/skinparse.h>
  6. #include <api/wac/compon.h>
  7. #include <api/wac/wac.h>
  8. #include <api/font/font.h>
  9. #include <bfc/parse/pathparse.h>
  10. #include <api/service/svcs/svc_collection.h>
  11. #include <tataki/canvas/bltcanvas.h>
  12. xml_elementtag elementtaglist[] =
  13. {
  14. {L"bitmap", XML_ELEMENTTAG_BITMAP, 0},
  15. {L"bitmapfont", XML_ELEMENTTAG_BITMAPFONT, 0},
  16. {L"color", XML_ELEMENTTAG_COLOR, 0},
  17. {L"cursor", XML_ELEMENTTAG_CURSOR, 0},
  18. {L"elements", XML_ELEMENTTAG_ELEMENTS, 1},
  19. {L"elementalias", XML_ELEMENTTAG_ELEMENTALIAS, 0},
  20. {L"truetypefont", XML_ELEMENTTAG_TRUETYPEFONT, 0},
  21. };
  22. //-------------------------
  23. //-------------------------
  24. void SkinElementsMgr::init()
  25. {
  26. if (!quickxmltaglist.getNumItems())
  27. {
  28. for (int i = 0;i < sizeof(elementtaglist) / sizeof(xml_elementtag);i++)
  29. quickxmltaglist.addItem(&elementtaglist[i]);
  30. }
  31. skinXML.registerCallback(L"WinampAbstractionLayer\felements\f*", &xmlreader); //back compat
  32. skinXML.registerCallback(L"WasabiXML\felements\f*", &xmlreader);
  33. }
  34. void SkinElementsMgr::deinit()
  35. {
  36. resetSkinElements();
  37. skinXML.unregisterCallback(&xmlreader);
  38. }
  39. void SkinElementsMgr::onBeforeLoadingSkinElements(const wchar_t *_rootpath)
  40. {
  41. Skin::sendBeforeLoadingElementsCallback();
  42. elementScriptId = WASABI_API_PALETTE->newSkinPart();
  43. WASABI_API_PALETTE->StartTransaction();
  44. rootpath = _rootpath;
  45. original_rootpath = rootpath;
  46. last_includepath = L"";
  47. }
  48. void SkinElementsMgr::onAfterLoadingSkinElements()
  49. {
  50. WASABI_API_PALETTE->EndTransaction();
  51. #ifdef WASABI_COMPILE_COMPONENTS
  52. ComponentManager::broadcastNotify(WAC_NOTIFY_SKINELEMENTSLOADED, Skin::getSkinPartIterator());
  53. #endif
  54. }
  55. void SkinElementsXmlReader::xmlReaderOnEndElementCallback(const wchar_t *xmltag)
  56. {
  57. SkinElementsMgr::xmlReaderOnEndElementCallback(xmltag);
  58. }
  59. void SkinElementsMgr::xmlReaderOnEndElementCallback(const wchar_t *xmltag)
  60. {
  61. xml_elementtag *i = quickxmltaglist.findItem(xmltag);
  62. if (!i) return ;
  63. if (i->id == XML_ELEMENTTAG_ELEMENTS)
  64. {
  65. if (inelements)
  66. inelements = 0;
  67. }
  68. }
  69. void SkinElementsXmlReader::xmlReaderOnStartElementCallback(const wchar_t *xmltag, skin_xmlreaderparams *params)
  70. {
  71. SkinElementsMgr::xmlReaderOnStartElementCallback(xmltag, params);
  72. }
  73. void SkinElementsMgr::xmlReaderOnStartElementCallback(const wchar_t *xmltag, skin_xmlreaderparams *params)
  74. {
  75. xml_elementtag *i = quickxmltaglist.findItem(xmltag);
  76. if (i)
  77. _xmlReaderOnStartElementCallback( i->id, xmltag, params);
  78. else
  79. _xmlReaderOnStartElementCallback( XML_ELEMENTTAG_UNKNOWN, xmltag, params);
  80. }
  81. void SkinElementsMgr::_xmlReaderOnStartElementCallback(int tagid, const wchar_t *xmltag, skin_xmlreaderparams *params)
  82. {
  83. const wchar_t *ic = skinXML.getIncludePath();
  84. if (WCSICMP(ic, last_includepath))
  85. {
  86. last_includepath = skinXML.getIncludePath();
  87. rootpath = getSkinRootpathFromIncludePath(last_includepath, original_rootpath);
  88. }
  89. // If we're loading from a buffer, there should be no rootpath prefix.
  90. if (!WCSNICMP(rootpath, L"buf:", 4))
  91. {
  92. rootpath = NULL;
  93. }
  94. if (tagid == XML_ELEMENTTAG_ELEMENTALIAS)
  95. {
  96. WASABI_API_PALETTE->AddAlias(params->getItemValue(L"id"), params->getItemValue(L"target"));
  97. }
  98. else if (tagid == XML_ELEMENTTAG_BITMAP)
  99. {
  100. StringW id;
  101. const wchar_t *fn;
  102. id = params->getItemValue(L"id");
  103. fn = params->getItemValue(L"file");
  104. int x = params->getItemValueInt(L"x", -1);
  105. int y = params->getItemValueInt(L"y", -1);
  106. int w = params->getItemValueInt(L"w", -1);
  107. int h = params->getItemValueInt(L"h", -1);
  108. const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
  109. if (aliastarget)
  110. id = aliastarget;
  111. const wchar_t *colorgroup = params->getItemValue(L"colorgroup");
  112. if (!colorgroup || !*colorgroup)
  113. colorgroup = params->getItemValue(L"gammagroup");
  114. WASABI_API_PALETTE->AddBitmap(id, fn, rootpath, x, y, w, h, params, colorgroup);
  115. }
  116. else if (tagid == XML_ELEMENTTAG_COLOR)
  117. {
  118. const wchar_t *colorstr = params->getItemValue(L"value");
  119. StringW id = params->getItemValue(L"id");
  120. const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
  121. if (aliastarget)
  122. id = aliastarget;
  123. const wchar_t *colorgroup = params->getItemValue(L"colorgroup");
  124. if (!colorgroup || !*colorgroup)
  125. colorgroup = params->getItemValue(L"gammagroup");
  126. if (!wcschr(colorstr, ','))
  127. {
  128. ARGB32 c = WASABI_API_PALETTE->getColorElement((colorstr));
  129. WASABI_API_PALETTE->AddColor(id, c, colorgroup, rootpath, params);
  130. }
  131. else
  132. {
  133. WASABI_API_PALETTE->AddColor((id), SkinParser::parseColor(colorstr), colorgroup, rootpath, params);
  134. }
  135. }
  136. else if (tagid == XML_ELEMENTTAG_BITMAPFONT)
  137. {
  138. Font::installBitmapFont(params->getItemValue(L"file"), rootpath, params->getItemValue(L"id"), params->getItemValueInt(L"charwidth", 0), params->getItemValueInt(L"charheight", 0), params->getItemValueInt(L"hspacing", 0), params->getItemValueInt(L"vspacing", 0), elementScriptId, params->getItemValueInt(L"allowmapping", 1));
  139. }
  140. else if (tagid == XML_ELEMENTTAG_TRUETYPEFONT)
  141. {
  142. Font::installTrueTypeFont(params->getItemValue(L"file"), rootpath, params->getItemValue(L"id"), elementScriptId, params->getItemValueInt(L"allowmapping", 1), 0);
  143. }
  144. else if (tagid == XML_ELEMENTTAG_CURSOR)
  145. {
  146. const wchar_t *bitmap = params->getItemValue(L"bitmap");
  147. StringW id = params->getItemValue(L"id");
  148. const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
  149. int x = params->getItemValueInt(L"hotspot_x", 0);
  150. int y = params->getItemValueInt(L"hotspot_y", 0);
  151. if (aliastarget)
  152. id = aliastarget;
  153. WASABI_API_PALETTE->AddCursor(id, bitmap, x, y, rootpath, params);
  154. }
  155. else if (tagid == XML_ELEMENTTAG_UNKNOWN)
  156. {
  157. CollectionSvcEnum cse(xmltag);
  158. svc_collection *svc;
  159. if (svc = cse.getFirst())
  160. { // got one!
  161. svc->addElement(params->getItemValue(L"id"), rootpath, elementScriptId, params);
  162. WASABI_API_SVC->service_release(svc);
  163. }
  164. }
  165. else
  166. {
  167. DebugStringW(L"SkinElementsMgr: tag %s was recognized but not handled!\n", xmltag);
  168. }
  169. }
  170. void SkinElementsMgr::resetSkinElements()
  171. {
  172. WASABI_API_PALETTE->Reset();
  173. Font::uninstallAll();
  174. // remove any element inserted into a hierarchical collection
  175. for (int i = 0;i < (int)WASABI_API_SVC->service_getNumServices(WaSvc::COLLECTION);i++)
  176. {
  177. waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::COLLECTION, i);
  178. if (f != NULL)
  179. {
  180. svc_collection *svc = static_cast<svc_collection*>(f->getInterface(FALSE));
  181. svc->removeAllElements();
  182. f->releaseInterface(svc);
  183. }
  184. }
  185. }
  186. void SkinElementsMgr::onBeforeLoadingScriptElements(const wchar_t *name, int script_id)
  187. {
  188. SkinElementsMgr::rootpathstack.addItem(new StringW(rootpath));
  189. oldid = elementScriptId;
  190. oldinel = inelements;
  191. WASABI_API_PALETTE->StartTransaction();
  192. wchar_t buf[WA_MAX_PATH] = {0};
  193. WCSCPYN(buf, name, WA_MAX_PATH);
  194. wchar_t *ptr = const_cast<wchar_t *>(Wasabi::Std::filename(buf));
  195. if (ptr != NULL) *ptr = '\0';
  196. rootpath = buf;
  197. rootpath.AddBackslash();
  198. original_rootpath = rootpath;
  199. last_includepath = L"";
  200. inelements = 0;
  201. elementScriptId = script_id;
  202. }
  203. void SkinElementsMgr::onAfterLoadingScriptElements()
  204. {
  205. WASABI_API_PALETTE->EndTransaction();
  206. elementScriptId = oldid;
  207. inelements = oldinel;
  208. rootpath = SkinElementsMgr::rootpathstack.getLast();
  209. delete SkinElementsMgr::rootpathstack.getLast();
  210. SkinElementsMgr::rootpathstack.removeLastItem();
  211. }
  212. void SkinElementsMgr::unloadScriptElements(int scriptid)
  213. {
  214. int i;
  215. WASABI_API_PALETTE->UnloadElements(scriptid);
  216. Font::uninstallByScriptId(scriptid);
  217. // remove any element inserted into a hierarchical collection
  218. for (i = 0;i < (int)WASABI_API_SVC->service_getNumServices(WaSvc::COLLECTION);i++)
  219. {
  220. waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::COLLECTION, i);
  221. if (f != NULL)
  222. {
  223. svc_collection *svc = static_cast<svc_collection*>(f->getInterface(FALSE));
  224. svc->removeElement(scriptid);
  225. f->releaseInterface(svc);
  226. }
  227. }
  228. }
  229. int SkinElementsMgr::elementEqual(const wchar_t *file1, const wchar_t *rootpath1,
  230. const wchar_t *file2, const wchar_t *rootpath2)
  231. {
  232. StringPathCombine a(rootpath1, file1);
  233. StringPathCombine b(rootpath2, file2);
  234. return PATHEQL(a, b);
  235. }
  236. const wchar_t *SkinElementsMgr::getSkinRootpathFromIncludePath(const wchar_t *includepath, const wchar_t *def)
  237. {
  238. if (!wcsstr(includepath, L"..")) return def;
  239. PathParserW pp(includepath);
  240. if (pp.getNumStrings() < 2 || !WCSCASEEQLSAFE(pp.enumString(0), L"skins")) // UNSAFE if the skinpath isn't "skins"
  241. return def;
  242. StringW baseskin = pp.enumString(1);
  243. if (wcsstr(includepath, L".."))
  244. {
  245. int x = 0;
  246. for (int i = 0;i < pp.getNumStrings();i++)
  247. {
  248. const wchar_t *p = pp.enumString(i);
  249. if (WCSICMP(p, L".."))
  250. {
  251. if (x == 1)
  252. baseskin = pp.enumString(i);
  253. x++;
  254. }
  255. else
  256. x--;
  257. }
  258. }
  259. t_rootpath = pp.enumString(0);
  260. t_rootpath.AppendFolder(baseskin);
  261. return t_rootpath;
  262. }
  263. SkinElementsXmlReader SkinElementsMgr::xmlreader;
  264. int SkinElementsMgr::inelements = 0;
  265. int SkinElementsMgr::elementScriptId = -1;
  266. int SkinElementsMgr::oldid, SkinElementsMgr::oldinel;
  267. StringW SkinElementsMgr::rootpath, SkinElementsMgr::original_rootpath, SkinElementsMgr::t_rootpath, SkinElementsMgr::last_includepath;
  268. PtrList<StringW> SkinElementsMgr::rootpathstack;
  269. PtrListQuickSorted<xml_elementtag, XmlElementTagComp> SkinElementsMgr::quickxmltaglist;