aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/skin/skinelem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/api/skin/skinelem.cpp')
-rw-r--r--Src/Wasabi/api/skin/skinelem.cpp316
1 files changed, 316 insertions, 0 deletions
diff --git a/Src/Wasabi/api/skin/skinelem.cpp b/Src/Wasabi/api/skin/skinelem.cpp
new file mode 100644
index 00000000..45d1a39f
--- /dev/null
+++ b/Src/Wasabi/api/skin/skinelem.cpp
@@ -0,0 +1,316 @@
+#include <precomp.h>
+#include <api.h>
+#include "skinelem.h"
+#include <api/skin/skin.h>
+#include <api/skin/skinparse.h>
+#include <api/wac/compon.h>
+#include <api/wac/wac.h>
+#include <api/font/font.h>
+#include <bfc/parse/pathparse.h>
+#include <api/service/svcs/svc_collection.h>
+#include <tataki/canvas/bltcanvas.h>
+
+xml_elementtag elementtaglist[] =
+ {
+ {L"bitmap", XML_ELEMENTTAG_BITMAP, 0},
+ {L"bitmapfont", XML_ELEMENTTAG_BITMAPFONT, 0},
+ {L"color", XML_ELEMENTTAG_COLOR, 0},
+ {L"cursor", XML_ELEMENTTAG_CURSOR, 0},
+ {L"elements", XML_ELEMENTTAG_ELEMENTS, 1},
+ {L"elementalias", XML_ELEMENTTAG_ELEMENTALIAS, 0},
+ {L"truetypefont", XML_ELEMENTTAG_TRUETYPEFONT, 0},
+ };
+
+//-------------------------
+
+
+
+
+
+
+
+//-------------------------
+
+void SkinElementsMgr::init()
+{
+ if (!quickxmltaglist.getNumItems())
+ {
+ for (int i = 0;i < sizeof(elementtaglist) / sizeof(xml_elementtag);i++)
+ quickxmltaglist.addItem(&elementtaglist[i]);
+ }
+ skinXML.registerCallback(L"WinampAbstractionLayer\felements\f*", &xmlreader); //back compat
+ skinXML.registerCallback(L"WasabiXML\felements\f*", &xmlreader);
+}
+
+void SkinElementsMgr::deinit()
+{
+ resetSkinElements();
+ skinXML.unregisterCallback(&xmlreader);
+}
+
+void SkinElementsMgr::onBeforeLoadingSkinElements(const wchar_t *_rootpath)
+{
+ Skin::sendBeforeLoadingElementsCallback();
+ elementScriptId = WASABI_API_PALETTE->newSkinPart();
+
+ WASABI_API_PALETTE->StartTransaction();
+
+ rootpath = _rootpath;
+ original_rootpath = rootpath;
+ last_includepath = L"";
+}
+
+void SkinElementsMgr::onAfterLoadingSkinElements()
+{
+ WASABI_API_PALETTE->EndTransaction();
+
+#ifdef WASABI_COMPILE_COMPONENTS
+ ComponentManager::broadcastNotify(WAC_NOTIFY_SKINELEMENTSLOADED, Skin::getSkinPartIterator());
+#endif
+}
+
+void SkinElementsXmlReader::xmlReaderOnEndElementCallback(const wchar_t *xmltag)
+{
+ SkinElementsMgr::xmlReaderOnEndElementCallback(xmltag);
+}
+
+void SkinElementsMgr::xmlReaderOnEndElementCallback(const wchar_t *xmltag)
+{
+ xml_elementtag *i = quickxmltaglist.findItem(xmltag);
+ if (!i) return ;
+ if (i->id == XML_ELEMENTTAG_ELEMENTS)
+ {
+ if (inelements)
+ inelements = 0;
+ }
+}
+
+void SkinElementsXmlReader::xmlReaderOnStartElementCallback(const wchar_t *xmltag, skin_xmlreaderparams *params)
+{
+ SkinElementsMgr::xmlReaderOnStartElementCallback(xmltag, params);
+}
+
+void SkinElementsMgr::xmlReaderOnStartElementCallback(const wchar_t *xmltag, skin_xmlreaderparams *params)
+{
+ xml_elementtag *i = quickxmltaglist.findItem(xmltag);
+ if (i)
+ _xmlReaderOnStartElementCallback( i->id, xmltag, params);
+ else
+ _xmlReaderOnStartElementCallback( XML_ELEMENTTAG_UNKNOWN, xmltag, params);
+}
+
+void SkinElementsMgr::_xmlReaderOnStartElementCallback(int tagid, const wchar_t *xmltag, skin_xmlreaderparams *params)
+{
+ const wchar_t *ic = skinXML.getIncludePath();
+ if (WCSICMP(ic, last_includepath))
+ {
+ last_includepath = skinXML.getIncludePath();
+ rootpath = getSkinRootpathFromIncludePath(last_includepath, original_rootpath);
+ }
+ // If we're loading from a buffer, there should be no rootpath prefix.
+ if (!WCSNICMP(rootpath, L"buf:", 4))
+ {
+ rootpath = NULL;
+ }
+ if (tagid == XML_ELEMENTTAG_ELEMENTALIAS)
+ {
+ WASABI_API_PALETTE->AddAlias(params->getItemValue(L"id"), params->getItemValue(L"target"));
+ }
+ else if (tagid == XML_ELEMENTTAG_BITMAP)
+ {
+ StringW id;
+ const wchar_t *fn;
+ id = params->getItemValue(L"id");
+ fn = params->getItemValue(L"file");
+ int x = params->getItemValueInt(L"x", -1);
+ int y = params->getItemValueInt(L"y", -1);
+ int w = params->getItemValueInt(L"w", -1);
+ int h = params->getItemValueInt(L"h", -1);
+
+ const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
+ if (aliastarget)
+ id = aliastarget;
+
+ const wchar_t *colorgroup = params->getItemValue(L"colorgroup");
+ if (!colorgroup || !*colorgroup)
+ colorgroup = params->getItemValue(L"gammagroup");
+
+ WASABI_API_PALETTE->AddBitmap(id, fn, rootpath, x, y, w, h, params, colorgroup);
+
+ }
+ else if (tagid == XML_ELEMENTTAG_COLOR)
+ {
+ const wchar_t *colorstr = params->getItemValue(L"value");
+ StringW id = params->getItemValue(L"id");
+ const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
+ if (aliastarget)
+ id = aliastarget;
+ const wchar_t *colorgroup = params->getItemValue(L"colorgroup");
+ if (!colorgroup || !*colorgroup)
+ colorgroup = params->getItemValue(L"gammagroup");
+ if (!wcschr(colorstr, ','))
+ {
+ ARGB32 c = WASABI_API_PALETTE->getColorElement((colorstr));
+ WASABI_API_PALETTE->AddColor(id, c, colorgroup, rootpath, params);
+ }
+ else
+ {
+ WASABI_API_PALETTE->AddColor((id), SkinParser::parseColor(colorstr), colorgroup, rootpath, params);
+ }
+ }
+ else if (tagid == XML_ELEMENTTAG_BITMAPFONT)
+ {
+ 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));
+ }
+ else if (tagid == XML_ELEMENTTAG_TRUETYPEFONT)
+ {
+ Font::installTrueTypeFont(params->getItemValue(L"file"), rootpath, params->getItemValue(L"id"), elementScriptId, params->getItemValueInt(L"allowmapping", 1), 0);
+ }
+ else if (tagid == XML_ELEMENTTAG_CURSOR)
+ {
+ const wchar_t *bitmap = params->getItemValue(L"bitmap");
+ StringW id = params->getItemValue(L"id");
+ const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
+ int x = params->getItemValueInt(L"hotspot_x", 0);
+ int y = params->getItemValueInt(L"hotspot_y", 0);
+ if (aliastarget)
+ id = aliastarget;
+ WASABI_API_PALETTE->AddCursor(id, bitmap, x, y, rootpath, params);
+ }
+ else if (tagid == XML_ELEMENTTAG_UNKNOWN)
+ {
+ CollectionSvcEnum cse(xmltag);
+ svc_collection *svc;
+ if (svc = cse.getFirst())
+ { // got one!
+ svc->addElement(params->getItemValue(L"id"), rootpath, elementScriptId, params);
+ WASABI_API_SVC->service_release(svc);
+ }
+ }
+ else
+ {
+ DebugStringW(L"SkinElementsMgr: tag %s was recognized but not handled!\n", xmltag);
+ }
+}
+
+void SkinElementsMgr::resetSkinElements()
+{
+ WASABI_API_PALETTE->Reset();
+
+ Font::uninstallAll();
+ // remove any element inserted into a hierarchical collection
+ for (int i = 0;i < (int)WASABI_API_SVC->service_getNumServices(WaSvc::COLLECTION);i++)
+ {
+ waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::COLLECTION, i);
+ if (f != NULL)
+ {
+ svc_collection *svc = static_cast<svc_collection*>(f->getInterface(FALSE));
+ svc->removeAllElements();
+ f->releaseInterface(svc);
+ }
+ }
+}
+
+void SkinElementsMgr::onBeforeLoadingScriptElements(const wchar_t *name, int script_id)
+{
+ SkinElementsMgr::rootpathstack.addItem(new StringW(rootpath));
+ oldid = elementScriptId;
+ oldinel = inelements;
+
+ WASABI_API_PALETTE->StartTransaction();
+ wchar_t buf[WA_MAX_PATH] = {0};
+ WCSCPYN(buf, name, WA_MAX_PATH);
+
+ wchar_t *ptr = const_cast<wchar_t *>(Wasabi::Std::filename(buf));
+ if (ptr != NULL) *ptr = '\0';
+ rootpath = buf;
+ rootpath.AddBackslash();
+
+ original_rootpath = rootpath;
+
+ last_includepath = L"";
+
+ inelements = 0;
+ elementScriptId = script_id;
+}
+
+void SkinElementsMgr::onAfterLoadingScriptElements()
+{
+ WASABI_API_PALETTE->EndTransaction();
+ elementScriptId = oldid;
+ inelements = oldinel;
+ rootpath = SkinElementsMgr::rootpathstack.getLast();
+ delete SkinElementsMgr::rootpathstack.getLast();
+ SkinElementsMgr::rootpathstack.removeLastItem();
+}
+
+void SkinElementsMgr::unloadScriptElements(int scriptid)
+{
+ int i;
+
+
+ WASABI_API_PALETTE->UnloadElements(scriptid);
+
+ Font::uninstallByScriptId(scriptid);
+ // remove any element inserted into a hierarchical collection
+ for (i = 0;i < (int)WASABI_API_SVC->service_getNumServices(WaSvc::COLLECTION);i++)
+ {
+ waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::COLLECTION, i);
+ if (f != NULL)
+ {
+ svc_collection *svc = static_cast<svc_collection*>(f->getInterface(FALSE));
+ svc->removeElement(scriptid);
+ f->releaseInterface(svc);
+ }
+ }
+}
+
+int SkinElementsMgr::elementEqual(const wchar_t *file1, const wchar_t *rootpath1,
+ const wchar_t *file2, const wchar_t *rootpath2)
+{
+
+ StringPathCombine a(rootpath1, file1);
+ StringPathCombine b(rootpath2, file2);
+
+ return PATHEQL(a, b);
+}
+
+const wchar_t *SkinElementsMgr::getSkinRootpathFromIncludePath(const wchar_t *includepath, const wchar_t *def)
+{
+ if (!wcsstr(includepath, L"..")) return def;
+
+ PathParserW pp(includepath);
+ if (pp.getNumStrings() < 2 || !WCSCASEEQLSAFE(pp.enumString(0), L"skins")) // UNSAFE if the skinpath isn't "skins"
+ return def;
+
+ StringW baseskin = pp.enumString(1);
+
+ if (wcsstr(includepath, L".."))
+ {
+ int x = 0;
+ for (int i = 0;i < pp.getNumStrings();i++)
+ {
+ const wchar_t *p = pp.enumString(i);
+ if (WCSICMP(p, L".."))
+ {
+ if (x == 1)
+ baseskin = pp.enumString(i);
+ x++;
+ }
+ else
+ x--;
+ }
+ }
+
+ t_rootpath = pp.enumString(0);
+ t_rootpath.AppendFolder(baseskin);
+ return t_rootpath;
+}
+
+SkinElementsXmlReader SkinElementsMgr::xmlreader;
+int SkinElementsMgr::inelements = 0;
+int SkinElementsMgr::elementScriptId = -1;
+int SkinElementsMgr::oldid, SkinElementsMgr::oldinel;
+StringW SkinElementsMgr::rootpath, SkinElementsMgr::original_rootpath, SkinElementsMgr::t_rootpath, SkinElementsMgr::last_includepath;
+PtrList<StringW> SkinElementsMgr::rootpathstack;
+PtrListQuickSorted<xml_elementtag, XmlElementTagComp> SkinElementsMgr::quickxmltaglist;