aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/imgldr
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/imgldr
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/imgldr')
-rw-r--r--Src/Wasabi/api/imgldr/ImgLoaderEnum.h24
-rw-r--r--Src/Wasabi/api/imgldr/api_imgldr.cpp20
-rw-r--r--Src/Wasabi/api/imgldr/api_imgldr.h98
-rw-r--r--Src/Wasabi/api/imgldr/imggen/grad.cpp60
-rw-r--r--Src/Wasabi/api/imgldr/imggen/grad.h15
-rw-r--r--Src/Wasabi/api/imgldr/imggen/imggen.cpp29
-rw-r--r--Src/Wasabi/api/imgldr/imggen/imggen.h14
-rw-r--r--Src/Wasabi/api/imgldr/imggen/osedge.cpp95
-rw-r--r--Src/Wasabi/api/imgldr/imggen/osedge.h13
-rw-r--r--Src/Wasabi/api/imgldr/imggen/poly.cpp59
-rw-r--r--Src/Wasabi/api/imgldr/imggen/poly.h13
-rw-r--r--Src/Wasabi/api/imgldr/imggen/shadowwnd.cpp152
-rw-r--r--Src/Wasabi/api/imgldr/imggen/shadowwnd.h40
-rw-r--r--Src/Wasabi/api/imgldr/imggen/solid.cpp67
-rw-r--r--Src/Wasabi/api/imgldr/imggen/solid.h14
-rw-r--r--Src/Wasabi/api/imgldr/imgldr.cpp554
-rw-r--r--Src/Wasabi/api/imgldr/imgldr.h86
-rw-r--r--Src/Wasabi/api/imgldr/imgldrapi.cpp81
-rw-r--r--Src/Wasabi/api/imgldr/imgldrapi.h23
-rw-r--r--Src/Wasabi/api/imgldr/skinbmps.h122
-rw-r--r--Src/Wasabi/api/imgldr/winbmp.h47
21 files changed, 1626 insertions, 0 deletions
diff --git a/Src/Wasabi/api/imgldr/ImgLoaderEnum.h b/Src/Wasabi/api/imgldr/ImgLoaderEnum.h
new file mode 100644
index 00000000..e71f4c4d
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/ImgLoaderEnum.h
@@ -0,0 +1,24 @@
+#ifndef __WASABI_IMGLOADERENUM_H
+#define __WASABI_IMGLOADERENUM_H
+
+#include <api/service/svc_enum.h>
+#include <bfc/string/StringW.h>
+
+class ImgLoaderEnum : public SvcEnumT<svc_imageLoader> {
+public:
+ ImgLoaderEnum(uint8_t *data, int datalen) : mem(datalen, data) { }
+ ImgLoaderEnum(const wchar_t *filename) : fname(filename) { }
+
+protected:
+ virtual int testService(svc_imageLoader *svc)
+ {
+ if (!fname.isempty() && !svc->isMine(fname)) return 0;
+ return svc->testData(mem, mem.getSizeInBytes());
+ }
+
+private:
+ StringW fname;
+ MemBlock<uint8_t> mem;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/imgldr/api_imgldr.cpp b/Src/Wasabi/api/imgldr/api_imgldr.cpp
new file mode 100644
index 00000000..20d03bcf
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/api_imgldr.cpp
@@ -0,0 +1,20 @@
+#include <precomp.h>
+#include "api_imgldr.h"
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+#define CBCLASS imgldr_apiI
+START_DISPATCH;
+ CB(IMGLDR_API_MAKEBMP, imgldr_makeBmp);
+#ifdef _WIN32
+ CB(IMGLDR_API_MAKEBMP2, imgldr_makeBmp2);
+#endif
+ VCB(IMGLDR_API_RELEASEBMP, imgldr_releaseBmp);
+#ifdef WASABI_COMPILE_SKIN
+ CB(IMGLDR_API_REQUESTSKINBITMAP, imgldr_requestSkinBitmap);
+ CB(IMGLDR_API_REQUESTSKINREGION, imgldr_requestSkinRegion);
+ VCB(IMGLDR_API_CACHESKINREGION, imgldr_cacheSkinRegion);
+ VCB(IMGLDR_API_RELEASESKINBITMAP, imgldr_releaseSkinBitmap);
+#endif //WASABI_COMPILE_SKIN
+END_DISPATCH;
diff --git a/Src/Wasabi/api/imgldr/api_imgldr.h b/Src/Wasabi/api/imgldr/api_imgldr.h
new file mode 100644
index 00000000..55e19bec
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/api_imgldr.h
@@ -0,0 +1,98 @@
+#ifndef __API_IMGLOADER_H
+#define __API_IMGLOADER_H
+
+#include <wasabicfg.h>
+#include <bfc/dispatch.h>
+
+class RegionServer;
+class api_region;
+
+class imgldr_api : public Dispatchable
+{
+public:
+ ARGB32 *imgldr_makeBmp(const wchar_t *filename, int *has_alpha, int *w, int *h);
+ ARGB32 *imgldr_makeBmp(OSMODULEHANDLE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *colorgroup = NULL);
+ void imgldr_releaseBmp(ARGB32 *bmpbits);
+ ARGB32 *imgldr_requestSkinBitmap(const wchar_t *file, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached);
+ RegionServer *imgldr_requestSkinRegion(const wchar_t *id);
+ void imgldr_cacheSkinRegion(const wchar_t *id, api_region *r);
+ void imgldr_releaseSkinBitmap(ARGB32 *bmpbits);
+
+ DISPATCH_CODES
+ {
+ IMGLDR_API_MAKEBMP = 0,
+ IMGLDR_API_MAKEBMP2 = 10,
+ IMGLDR_API_RELEASEBMP = 20,
+ IMGLDR_API_REQUESTSKINBITMAP = 30,
+ IMGLDR_API_REQUESTSKINREGION = 40,
+ IMGLDR_API_CACHESKINREGION = 50,
+ IMGLDR_API_RELEASESKINBITMAP = 60,
+ };
+};
+
+inline ARGB32 *imgldr_api::imgldr_makeBmp(const wchar_t *filename, int *has_alpha, int *w, int *h)
+{
+ return _call(IMGLDR_API_MAKEBMP, (ARGB32 *)NULL, filename, has_alpha, w, h);
+}
+
+inline ARGB32 *imgldr_api::imgldr_makeBmp(OSMODULEHANDLE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *colorgroup)
+{
+ return _call(IMGLDR_API_MAKEBMP2, (ARGB32 *)NULL, hInst, id, has_alpha, w, h, colorgroup);
+}
+
+inline void imgldr_api::imgldr_releaseBmp(ARGB32 *bmpbits)
+{
+ _voidcall(IMGLDR_API_RELEASEBMP, bmpbits);
+}
+
+#ifdef WASABI_COMPILE_SKIN
+
+inline ARGB32 *imgldr_api::imgldr_requestSkinBitmap(const wchar_t *file, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached)
+{
+ return _call(IMGLDR_API_REQUESTSKINBITMAP, (ARGB32 *)NULL, file, has_alpha, x, y, subw, subh, w, h, cached);
+}
+
+inline RegionServer *imgldr_api::imgldr_requestSkinRegion(const wchar_t *id)
+{
+ return _call(IMGLDR_API_REQUESTSKINREGION, (RegionServer *)NULL, id);
+}
+
+inline void imgldr_api::imgldr_cacheSkinRegion(const wchar_t *id, api_region *r)
+{
+ _voidcall(IMGLDR_API_CACHESKINREGION, id, r);
+}
+
+inline void imgldr_api::imgldr_releaseSkinBitmap(ARGB32 *bmpbits)
+{
+ _voidcall(IMGLDR_API_RELEASESKINBITMAP, bmpbits);
+}
+
+#endif //WASABI_COMPILE_SKIN
+
+class imgldr_apiI : public imgldr_api
+{
+public:
+ virtual ARGB32 *imgldr_makeBmp(const wchar_t *filename, int *has_alpha, int *w, int *h) = 0;
+#ifdef _WIN32
+ virtual ARGB32 *imgldr_makeBmp2(OSMODULEHANDLE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *colorgroup = NULL) = 0;
+#endif
+ virtual void imgldr_releaseBmp(ARGB32 *bmpbits) = 0;
+#ifdef WASABI_COMPILE_SKIN
+ virtual ARGB32 *imgldr_requestSkinBitmap(const wchar_t *file, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached) = 0;
+ virtual RegionServer *imgldr_requestSkinRegion(const wchar_t *id) = 0;
+ virtual void imgldr_cacheSkinRegion(const wchar_t *id, api_region *r) = 0;
+ virtual void imgldr_releaseSkinBitmap(ARGB32 *bmpbits) = 0;
+#endif //WASABI_COMPILE_SKIN
+
+protected:
+ RECVS_DISPATCH;
+};
+
+// {703ECC7C-B3D8-4e1e-B8B5-A7563D9D6F30}
+static const GUID imgLdrApiServiceGuid =
+ { 0x703ecc7c, 0xb3d8, 0x4e1e, { 0xb8, 0xb5, 0xa7, 0x56, 0x3d, 0x9d, 0x6f, 0x30 } };
+
+extern imgldr_api *imgLoaderApi;
+
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/imggen/grad.cpp b/Src/Wasabi/api/imgldr/imggen/grad.cpp
new file mode 100644
index 00000000..acec2eab
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/grad.cpp
@@ -0,0 +1,60 @@
+#include "precomp.h"
+
+#include "grad.h"
+
+#include <api/xml/xmlparams.h>
+#include <api/memmgr/api_memmgr.h>
+#ifndef _WASABIRUNTIME
+
+BEGIN_SERVICES(GradientGen_Svc);
+DECLARE_SERVICETSINGLE(svc_imageGenerator, GradientImage);
+END_SERVICES(GradientGen_Svc, _GradientGen_Svc);
+
+#ifdef _X86_
+extern "C" { int _link_GradientGen_Svc; }
+#else
+extern "C" { int __link_GradientGen_Svc; }
+#endif
+
+#endif
+
+
+int GradientImage::testDesc(const wchar_t *desc) {
+ return !_wcsicmp(desc, L"$gradient");
+}
+
+ARGB32 *GradientImage::genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params)
+{
+ int _w = params->getItemValueInt(L"w",1);
+ if (_w == 0) _w = 1;
+ int _h = params->getItemValueInt(L"h",1);
+ if (_h == 0) _h = 1;
+ if (_w <= 0 || _h <= 0) return NULL;
+
+#ifdef WASABI_COMPILE_MEMMGR
+ ARGB32 *ret = (ARGB32*)WASABI_API_MEMMGR->sysMalloc(_w * _h * sizeof(ARGB32));
+#else
+ ARGB32 *ret = (ARGB32*)MALLOC(_w * _h * sizeof(ARGB32));
+#endif
+
+ setX1((float)WTOF(params->getItemValue(L"gradient_x1")));
+ setY1((float)WTOF(params->getItemValue(L"gradient_y1")));
+ setX2((float)WTOF(params->getItemValue(L"gradient_x2")));
+ setY2((float)WTOF(params->getItemValue(L"gradient_y2")));
+
+ setPoints(params->getItemValue(L"points"));
+
+ setMode(params->getItemValue(L"mode"));
+
+ setReverseColors(TRUE); // cuz we're imggen
+
+ setAntialias(params->getItemValueInt(L"antialias"));
+
+ renderGradient(ret, _w, _h);
+
+ *w = _w;
+ *h = _h;
+ *has_alpha = 1; // will be optimized anyway
+
+ return ret;
+}
diff --git a/Src/Wasabi/api/imgldr/imggen/grad.h b/Src/Wasabi/api/imgldr/imggen/grad.h
new file mode 100644
index 00000000..8ee4c886
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/grad.h
@@ -0,0 +1,15 @@
+#ifndef _GRAD_H
+#define _GRAD_H
+
+#include <api/service/svcs/svc_imggen.h>
+#include <bfc/draw/gradient.h>
+
+class GradientImage : public svc_imageGeneratorI, public Gradient
+{
+public:
+ static const char *getServiceName() { return "Gradient image generator"; }
+ virtual int testDesc(const wchar_t *desc);
+ virtual ARGB32 *genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params=NULL);
+};
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/imggen/imggen.cpp b/Src/Wasabi/api/imgldr/imggen/imggen.cpp
new file mode 100644
index 00000000..bcf0b6d4
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/imggen.cpp
@@ -0,0 +1,29 @@
+#include "precomp.h"
+#include "imggen.h"
+
+#include "solid.h"
+#include "grad.h"
+#include "osedge.h"
+#include "poly.h"
+#include "shadowwnd.h"
+
+#include "../studio/services/servicei.h"
+
+static WACNAME wac;
+WAComponentClient *the = &wac;
+
+// {9C9CB15E-2904-4df2-B8CE-FFBC6CD230DC}
+static const GUID guid =
+{ 0x9c9cb15e, 0x2904, 0x4df2, { 0xb8, 0xce, 0xff, 0xbc, 0x6c, 0xd2, 0x30, 0xdc } };
+
+WACNAME::WACNAME() {
+ registerService(new waServiceFactoryTSingle<svc_imageGenerator, SolidImage>);
+ registerService(new waServiceFactoryTSingle<svc_imageGenerator, GradientImage>);
+ registerService(new waServiceFactoryTSingle<svc_imageGenerator, OsEdgeImage>);
+ registerService(new waServiceFactoryTSingle<svc_imageGenerator, PolyImage>);
+ registerService(new XuiObjectCreator<XuiShadowWndSvc>);
+}
+
+GUID WACNAME::getGUID() {
+ return guid;
+}
diff --git a/Src/Wasabi/api/imgldr/imggen/imggen.h b/Src/Wasabi/api/imgldr/imggen/imggen.h
new file mode 100644
index 00000000..9af473d5
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/imggen.h
@@ -0,0 +1,14 @@
+#ifndef _IMGGEN_H
+#define _IMGGEN_H
+
+#include "../studio/wac.h"
+
+#define WACNAME WACimggen
+class WACNAME : public WAComponentClient {
+public:
+ WACNAME();
+
+ virtual const char *getName() { return "Standard Image Generators"; };
+ virtual GUID getGUID();
+};
+#endif
diff --git a/Src/Wasabi/api/imgldr/imggen/osedge.cpp b/Src/Wasabi/api/imgldr/imggen/osedge.cpp
new file mode 100644
index 00000000..c699a860
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/osedge.cpp
@@ -0,0 +1,95 @@
+#include "precomp.h"
+
+#include "osedge.h"
+#include <api/xml/xmlparams.h>
+#include <bfc/parse/pathparse.h>
+#include <api/memmgr/api_memmgr.h>
+#ifndef _WASABIRUNTIME
+
+BEGIN_SERVICES(OsEdgeGen_Svc);
+DECLARE_SERVICETSINGLE(svc_imageGenerator, OsEdgeImage);
+END_SERVICES(OsEdgeGen_Svc, _OsEdgeGen_Svc);
+
+#ifdef _X86_
+extern "C" { int _link_OsEdgeGen_Svc; }
+#else
+extern "C" { int __link_OsEdgeGen_Svc; }
+#endif
+
+#endif
+
+
+int OsEdgeImage::testDesc(const wchar_t *desc) {
+ return !_wcsicmp(desc, L"$osedge");
+}
+
+ARGB32 *OsEdgeImage::genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params)
+{
+ int _w = params->getItemValueInt(L"w", 1);
+ if (_w == 0) _w = 1;
+ int _h = params->getItemValueInt(L"h", 1);
+ if (_h == 0) _h = 1;
+ if (_w <= 0 || _h <= 0) return NULL;
+
+#ifdef WASABI_COMPILE_MEMMGR
+ ARGB32 *ret = (ARGB32*)WASABI_API_MEMMGR->sysMalloc(_w * _h * sizeof(ARGB32));
+#else
+ ARGB32 *ret = (ARGB32*)MALLOC(_w * _h * sizeof(ARGB32));
+#endif
+
+ RECT r = Wasabi::Std::makeRect(0, 0, _w, _h);
+
+ BITMAPINFO bmi;
+ ZERO(bmi);
+ bmi.bmiHeader.biSize = sizeof(bmi);
+ bmi.bmiHeader.biWidth = _w;
+ bmi.bmiHeader.biHeight = -_h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ // the rest are 0
+ ARGB32 *bits;
+ HBITMAP hbmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+ HDC hdc = CreateCompatibleDC(NULL);
+ HBITMAP prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
+
+ unsigned long edgev = 0;
+ if (!_wcsicmp(params->getItemValue(L"edge"), L"bump")) edgev = EDGE_BUMP;
+ else if (!_wcsicmp(params->getItemValue(L"edge"), L"etched")) edgev = EDGE_ETCHED;
+ else if (!_wcsicmp(params->getItemValue(L"edge"), L"raised")) edgev = EDGE_RAISED;
+ else if (!_wcsicmp(params->getItemValue(L"edge"), L"sunken")) edgev = EDGE_SUNKEN;
+ if (edgev == 0) edgev = EDGE_RAISED;
+
+ unsigned long sides = 0;
+ PathParserW pp(params->getItemValue(L"sides"), L",");
+ for (int i = 0; i < pp.getNumStrings(); i++) {
+ const wchar_t *p = pp.enumString(i);
+ if (!_wcsicmp(p, L"left")) sides |= BF_LEFT;
+ if (!_wcsicmp(p, L"top")) sides |= BF_TOP;
+ if (!_wcsicmp(p, L"right")) sides |= BF_RIGHT;
+ if (!_wcsicmp(p, L"bottom")) sides |= BF_BOTTOM;
+ if (!_wcsicmp(p, L"all")) sides |= BF_RECT;
+ if (!_wcsicmp(p, L"middle")) sides |= BF_MIDDLE;
+ if (!_wcsicmp(p, L"flat")) sides |= BF_FLAT;
+ if (!_wcsicmp(p, L"soft")) sides |= BF_SOFT;
+ if (!_wcsicmp(p, L"mono")) sides |= BF_MONO;
+ }
+
+// DO EET
+ DrawEdge(hdc, &r, edgev, sides);
+
+ MEMCPY(ret, bits, sizeof(ARGB32) * _w * _h);
+ for (int i = 0; i < _w * _h; i++) { // force alpha
+ ret[i] |= 0xff000000;
+ }
+
+ SelectObject(hdc, prevbmp);
+ DeleteDC(hdc);
+ DeleteObject(hbmp);
+
+ *w = _w;
+ *h = _h;
+ *has_alpha = 1; // will be optimized anyway
+
+ return ret;
+}
diff --git a/Src/Wasabi/api/imgldr/imggen/osedge.h b/Src/Wasabi/api/imgldr/imggen/osedge.h
new file mode 100644
index 00000000..f00771a1
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/osedge.h
@@ -0,0 +1,13 @@
+#ifndef _OSEDGE_H
+#define _OSEDGE_H
+
+#include <api/service/svcs/svc_imggen.h>
+
+class OsEdgeImage : public svc_imageGeneratorI {
+public:
+ static const char *getServiceName() { return "OS Edge image generator"; }
+ virtual int testDesc(const wchar_t *desc);
+ virtual ARGB32 *genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params=NULL);
+};
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/imggen/poly.cpp b/Src/Wasabi/api/imgldr/imggen/poly.cpp
new file mode 100644
index 00000000..086664e8
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/poly.cpp
@@ -0,0 +1,59 @@
+#include "precomp.h"
+
+#include "poly.h"
+
+#include <api/xml/xmlparams.h>
+#include <api/memmgr/api_memmgr.h>
+#ifndef _WASABIRUNTIME
+
+BEGIN_SERVICES(PolyGen_Svc);
+DECLARE_SERVICETSINGLE(svc_imageGenerator, PolyImage);
+END_SERVICES(PolyGen_Svc, _PolyGen_Svc);
+
+#ifdef _X86_
+extern "C" { int _link_PolyGen_Svc; }
+#else
+extern "C" { int __link_PolyGen_Svc; }
+#endif
+
+#endif
+
+int PolyImage::testDesc(const wchar_t *desc) {
+ return !_wcsicmp(desc, L"$polygon");
+}
+
+void premultiply(ARGB32 *m_pBits, int nwords);
+
+#include <bfc/draw/drawpoly.h>
+
+ARGB32 *PolyImage::genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params)
+{
+ int _w = (params->getItemValueInt(L"w", 1));
+ if (_w == 0) _w = 1;
+ int _h = (params->getItemValueInt(L"h", 1));
+ if (_h == 0) _h = 1;
+ if (_w <= 0 || _h <= 0) return NULL;
+
+ const wchar_t *bgcolorstr = params->getItemValue(L"bgcolor");
+ ARGB32 bgcolor = (bgcolorstr == NULL || *bgcolorstr=='\0') ? 0 : _byteswap_ulong(WASABI_API_SKIN->parse(params->getItemValue(L"bgcolor"), L"color")<<8);
+
+ unsigned int bgalpha = params->getItemValueInt(L"bgalpha", 0);
+ bgcolor |= ((bgalpha & 0xff) << 24);
+
+ premultiply(&bgcolor, 1);
+
+#ifdef WASABI_COMPILE_MEMMGR
+ ARGB32 *ret = (ARGB32*)WASABI_API_MEMMGR->sysMalloc(_w * _h * sizeof(ARGB32));
+#else
+ ARGB32 *ret = (ARGB32*)MALLOC(_w * _h * sizeof(ARGB32));
+#endif
+
+ MEMFILL<ARGB32>(ret, bgcolor, _w * _h);
+
+ Draw::drawPointList(ret, _w, _h, params->getItemValue(L"points"));
+
+ *w = _w;
+ *h = _h;
+ *has_alpha = 1;
+ return ret;
+}
diff --git a/Src/Wasabi/api/imgldr/imggen/poly.h b/Src/Wasabi/api/imgldr/imggen/poly.h
new file mode 100644
index 00000000..07095056
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/poly.h
@@ -0,0 +1,13 @@
+#ifndef _POLY_H
+#define _POLY_H
+
+#include <api/service/svcs/svc_imggen.h>
+
+class PolyImage : public svc_imageGeneratorI {
+public:
+ static const char *getServiceName() { return "Polygon image generator"; }
+ virtual int testDesc(const wchar_t *desc);
+ virtual ARGB32 *genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params=NULL);
+};
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/imggen/shadowwnd.cpp b/Src/Wasabi/api/imgldr/imggen/shadowwnd.cpp
new file mode 100644
index 00000000..fb61c95c
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/shadowwnd.cpp
@@ -0,0 +1,152 @@
+#include "precomp.h"
+
+#include "shadowwnd.h"
+
+#include "../bfc/canvas.h"
+#include "../bfc/region.h"
+
+enum { TARGET };
+
+char XuiShadowWndParams[][]=
+{
+ "TARGET",
+};
+XuiShadowWnd::XuiShadowWnd() {
+ myxuihandle = newXuiHandle();
+ addParam(myxuihandle, XuiShadowWndParams[0], TARGET, XUI_ATTRIBUTE_REQUIRED);
+ group = NULL;
+ bltcanvas = NULL;
+ c_w = c_h = 0;
+ in_paint = 0;
+}
+
+XuiShadowWnd::~XuiShadowWnd() {
+ delete bltcanvas;
+}
+
+int XuiShadowWnd::onInit() {
+ XUISHADOWWND_PARENT::onInit();
+
+DebugString("on iniiit");
+
+ attachToGroup();
+setTimer(10, 50);
+
+ return 1;
+}
+
+void XuiShadowWnd::timerclient_timerCallback(int id) {
+ if (id == 10) {
+ if (group == NULL) attachToGroup();
+ delete bltcanvas;
+ RECT r; group->getClientRect(&r);
+ bltcanvas = new BltCanvas(r.right - r.left, r.bottom - r.top);
+ in_paint++;
+ group->paint(bltcanvas);
+MEMFILL<ARGB32>((unsigned long *)bltcanvas->getBits(), 0xffffffff, (r.right - r.left) * 20);
+ in_paint--;
+ invalidate();
+ } else
+ XUISHADOWWND_PARENT::timerclient_timerCallback(id);
+}
+
+int XuiShadowWnd::onPaint(Canvas *canvas) {
+#if 0
+if (group == NULL) attachToGroup();
+if (group == NULL) { DebugString("groupNull"); }
+if (group == NULL) return 0;
+
+#endif
+DebugString("begin painting");
+
+if (in_paint++) {
+// RECT cr = clientRect();
+// canvas->fillRect(&cr, RGB(255,0,255));
+//MEMFILL<ARGB32>((unsigned long *)canvas->getBits(), 0xffffffff, (cr.right - cr.left) * 20);
+DebugString("filla!");
+} else {
+#if 0
+ RECT cr;
+ group->getClientRect(&cr);
+ SkinBitmap *bm
+bltcanvas->blit(0, 0,
+BltCanvas c(cr.right - cr.left, cr.bottom - cr.top);
+group->paint(&c);
+#if 0
+c.pushPen(0,255,0);
+c.lineDraw(0, 0, cr.right, cr.bottom);
+/c.popPen();
+#endif
+MEMFILL<ARGB32>((unsigned long *)c.getBits(), 0xffffffff, (cr.right - cr.left) * 20);
+c.blit(0, 0, canvas, 0, 0, cr.right - cr.left, cr.bottom - cr.top);
+
+DebugString("get from group!");
+#endif
+ if (bltcanvas != NULL) {
+ SkinBitmap *bm = bltcanvas->getSkinBitmap();
+ bm->stretchToRectAlpha(canvas, &clientRect(), getPaintingAlpha());
+DebugString("bleet!");
+ }
+}
+in_paint--;
+ return 1;
+}
+
+int XuiShadowWnd::setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value) {
+ if (xuihandle != myxuihandle)
+ return XUISHADOWWND_PARENT::setXuiParam(xuihandle, xmlattributeid, xmlattributename, value);
+ switch (xmlattributeid) {
+ case TARGET:
+ targetname = value;
+DebugString("set target %s", value);
+ if (isPostOnInit()) attachToGroup();
+ break;
+ default: return 0;
+ }
+ return 1;
+}
+
+void XuiShadowWnd::attachToGroup() {
+ if (targetname.isempty()) return;
+ group = findWindow(targetname);
+ if (group == NULL) return;
+ monitorWindow(group);
+DebugString("attached to group rw %d", group);
+
+ delete bltcanvas; bltcanvas = NULL;
+}
+
+void XuiShadowWnd::onAfterPaint(PaintCallbackInfo *info) {
+DebugString("after paint");
+#if 0
+ RECT ncr;
+ group->getNonClientRect(&ncr);
+ c_w = ncr.right - ncr.left;
+ c_h = ncr.bottom - ncr.top;
+
+DebugString("w %d h %d", c_w, c_h);
+
+ delete bltcanvas; bltcanvas = NULL;
+ if (c_w != 0 && c_h != 0) bltcanvas = new BltCanvas(c_w, c_h);
+
+ Canvas *c = info->getCanvas();
+ api_region *r = info->getRegion();
+ // blit what changed
+ RegionI saved;
+ c->getClipRgn(&saved);
+ bltcanvas->selectClipRgn(r);
+ c->blit(0, 0, bltcanvas, 0, 0, c_w, c_h);
+ c->selectClipRgn(&saved);
+
+ invalidate();
+#endif
+}
+
+void XuiShadowWnd::onInvalidation(PaintCallbackInfo *info) {
+// invalidate();
+DebugString("got invalidate");
+}
+
+void XuiShadowWnd::onWindowDeleted(api_window *w) {
+ if (w == group) group = NULL;
+}
diff --git a/Src/Wasabi/api/imgldr/imggen/shadowwnd.h b/Src/Wasabi/api/imgldr/imggen/shadowwnd.h
new file mode 100644
index 00000000..8082dba5
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/shadowwnd.h
@@ -0,0 +1,40 @@
+#ifndef _SHADOW_H
+#define _SHADOW_H
+
+#include "../common/guiobjwnd.h"
+#include "../bfc/paintcb.h"
+
+#define XUISHADOWWND_PARENT GuiObjectWnd
+class XuiShadowWnd : public XUISHADOWWND_PARENT, public PaintCallback {
+public:
+ static const wchar_t *xuiobject_getXmlTag() { return "Shadow"; }
+ static const char *xuiobject_getServiceName() { return "Shadow XuiObject"; }
+
+ XuiShadowWnd();
+ virtual ~XuiShadowWnd();
+
+ virtual int onInit();
+
+ virtual int onPaint(Canvas *canvas);
+
+ virtual int setXuiParam(int xuihandle, int xmlattributeid, const wchar_t *xmlattributename, const wchar_t *value);
+
+ virtual void onAfterPaint(PaintCallbackInfo *info);
+ virtual void onInvalidation(PaintCallbackInfo *info);
+protected:
+ virtual void onWindowDeleted(BaseWnd *w);
+ void attachToGroup();
+ virtual void timerclient_timerCallback(int id);
+
+private:
+ int myxuihandle;
+ StringW targetname;
+ api_window *group;
+ BltCanvas *bltcanvas;
+ int c_w, c_h;
+ int in_paint;
+};
+
+class XuiShadowWndSvc : public XuiObjectSvc2<XuiShadowWnd> {};
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/imggen/solid.cpp b/Src/Wasabi/api/imgldr/imggen/solid.cpp
new file mode 100644
index 00000000..7f461eaa
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/solid.cpp
@@ -0,0 +1,67 @@
+#include "precomp.h"
+
+#include "solid.h"
+#include <api/xml/xmlparams.h>
+#include <api/memmgr/api_memmgr.h>
+
+#ifndef _WASABIRUNTIME
+
+BEGIN_SERVICES(SolidGen_Svc);
+DECLARE_SERVICETSINGLE(svc_imageGenerator, SolidImage);
+END_SERVICES(SolidGen_Svc, _SolidGen_Svc);
+
+#ifdef _X86_
+extern "C" { int _link_SolidGen_Svc; }
+#else
+extern "C" { int __link_SolidGen_Svc; }
+#endif
+
+#endif
+
+int SolidImage::testDesc(const wchar_t *desc)
+{
+ return !WCSICMP(desc, L"$solid");
+}
+
+void premultiply(ARGB32 *m_pBits, int nwords)
+{
+ for (; nwords > 0; nwords--, m_pBits++)
+ {
+ unsigned __int8 *pixel = (unsigned __int8 *)m_pBits;
+ unsigned int alpha = pixel[3];
+ if (alpha == 255) continue;
+ pixel[0] = (pixel[0] * alpha) >> 8; // blue
+ pixel[1] = (pixel[1] * alpha) >> 8; // green
+ pixel[2] = (pixel[2] * alpha) >> 8; // red
+ }
+}
+
+ARGB32 *SolidImage::genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params)
+{
+ int _w = params->getItemValueInt(L"w", 1);
+ if (_w == 0) _w = 1;
+ int _h = params->getItemValueInt(L"h", 1);
+ if (_h == 0) _h = 1;
+ if (_w <= 0 || _h <= 0) return NULL;
+ ARGB32 color = _byteswap_ulong(WASABI_API_SKIN->parse(params->getItemValue(L"color"), L"color") << 8);
+
+ unsigned int alpha = params->getItemValueInt(L"alpha", 255);
+ color |= ((alpha & 0xff) << 24);
+
+ premultiply(&color, 1);
+
+#ifdef WASABI_COMPILE_MEMMGR
+ ARGB32 *ret = (ARGB32*)WASABI_API_MEMMGR->sysMalloc(_w * _h * sizeof(ARGB32));
+#else
+ ARGB32 *ret = (ARGB32*)MALLOC(_w * _h * sizeof(ARGB32));
+#endif
+
+ MEMFILL<ARGB32>(ret, color, _w * _h);
+
+ *w = _w;
+ *h = _h;
+
+ *has_alpha = (alpha == 255) ? 0 : 1;
+
+ return ret;
+}
diff --git a/Src/Wasabi/api/imgldr/imggen/solid.h b/Src/Wasabi/api/imgldr/imggen/solid.h
new file mode 100644
index 00000000..d810bc1c
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imggen/solid.h
@@ -0,0 +1,14 @@
+#ifndef _SOLID_H
+#define _SOLID_H
+
+#include <api/service/svcs/svc_imggen.h>
+
+class SolidImage : public svc_imageGeneratorI
+{
+public:
+ static const char *getServiceName() { return "Solid Color image generator"; }
+ virtual int testDesc(const wchar_t *desc);
+ virtual ARGB32 *genImage(const wchar_t *desc, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params = NULL);
+};
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/imgldr.cpp b/Src/Wasabi/api/imgldr/imgldr.cpp
new file mode 100644
index 00000000..d7e33b54
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imgldr.cpp
@@ -0,0 +1,554 @@
+#include <precomp.h>
+#include <setjmp.h>
+#include <bfc/bfc_assert.h>
+#include <api.h>
+
+#include <bfc/wasabi_std.h>
+#include <tataki/bitmap/bitmap.h>
+#include <api/skin/skinfilter.h> // ApplySkinFilters
+
+#include "imgldr.h"
+#ifdef _WIN32
+#include <api/imgldr/winbmp.h>
+#endif
+#include <api/imgldr/skinbmps.h>
+
+#include <api/skin/skinparse.h>
+#include <api/skin/skinelem.h>
+#include <api/skin/gammamgr.h>
+
+#include <api/service/svcs/svc_skinfilter.h>
+#include <api/service/svcs/svc_imgload.h>
+#include <api/service/svcs/svc_imggen.h>
+#include "ImgLoaderEnum.h"
+#include <api/memmgr/api_memmgr.h>
+#include <bfc/string/PathString.h>
+#include <api/locales/localesmgr.h>
+
+//#define DEBUG_OUTPUT
+
+#define IMAGEHEADERLEN 256
+
+#ifdef _WIN32
+ARGB32 *imageLoader::makeBmp(OSMODULEHANDLE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *forcegroup)
+{
+ ARGB32 *bits = makeBmp(StringPrintfW(L"res://%u,%i", hInst, id), NULL, has_alpha, w, h, NULL, TRUE, NULL);
+ if (bits && *w > 0 && *h > 0)
+ {
+ ApplySkinFilters::apply(StringPrintfW(L"resource:%x,%d", hInst, id), forcegroup, bits, *w, *h);
+ }
+ return bits;
+}
+#endif
+
+StringW imageLoader::getWallpaper()
+{
+ StringW ret(L"");
+#ifdef WIN32
+ HKEY hkey;
+ static wchar_t file[MAX_PATH];
+ file[0] = 0;
+ if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), &hkey) == ERROR_SUCCESS)
+ {
+ unsigned long len = MAX_PATH;
+ RegQueryValueExW(hkey, L"Wallpaper", 0, NULL, (unsigned char *)&file, &len);
+ RegCloseKey(hkey);
+ }
+ if (file[0] && GetFileAttributesW(file) != (DWORD) - 1) ret = file;
+#endif
+ return ret;
+}
+extern StringW g_resourcepath;
+
+ARGB32 *imageLoader::makeBmp(const wchar_t *_filename, const wchar_t *path, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params, bool addMem, int *force_nocache)
+{
+ if (!_filename || !*_filename)
+ return 0;
+
+
+ ARGB32 *ret = NULL;
+
+ if (has_alpha != NULL)
+ *has_alpha = 0; //BU
+
+ // test image generator services FIRST
+ ImgGeneratorEnum ige(_filename);
+ svc_imageGenerator *gen;
+ while ((gen = ige.getNext()) != NULL)
+ {
+ ret = gen->genImage(_filename, has_alpha, w, h, params);
+ int cacheable = gen->outputCacheable();
+ ige.release(gen);
+ if (ret != NULL)
+ {
+ ApplySkinFilters::apply(params->getItemValue(L"id"), params->getItemValue(L"gammagroup"), ret, *w, *h);
+ if (addMem) addMemUsage(_filename, (*w) * (*h) * sizeof(int));
+ optimizeHasAlpha(ret, *w * *h, has_alpha);
+ // don't try to cache generated images
+ if (force_nocache) *force_nocache = !cacheable;
+ return ret;
+ }
+ }
+
+ StringW wallpaper;
+ if (!WCSICMP(_filename, L"$wallpaper"))
+ {
+ wallpaper = getWallpaper();
+ _filename = wallpaper.getValue();
+ }
+
+ MemBlock<uint8_t> mem;
+
+ wchar_t olddir[PATH_MAX] = {0};
+ Wasabi::Std::getCurDir(olddir, PATH_MAX);
+ Wasabi::Std::setCurDir(WASABI_API_APP->path_getAppPath());
+
+ StringW file;
+
+ // benski> try language pack first
+ StringPathCombine skinLocalePath(LocalesManager::getLocaleRoot(), WASABI_API_SKIN->getSkinName());
+ file.swap(StringPathCombine(skinLocalePath, _filename));
+ OSFILETYPE in = WFOPEN(file, WF_READONLY_BINARY);
+
+ if (in == OPEN_FAILED)
+ {
+ // try the language pack's folder itself before falling back to the resource path
+ file.swap(StringPathCombine(LocalesManager::getLocaleRoot(), _filename));
+ in = WFOPEN(file, WF_READONLY_BINARY);
+ }
+
+ if (in == OPEN_FAILED)
+ {
+ if (path)
+ {
+ file.swap(StringPathCombine(path, _filename));
+ in = WFOPEN(file, WF_READONLY_BINARY);
+ }
+ else
+ in = WFOPEN(file=_filename, WF_READONLY_BINARY);
+ }
+
+#ifdef WASABI_COMPILE_SKIN
+ if (in == OPEN_FAILED)
+ {
+ file.swap(StringPathCombine(WASABI_API_SKIN->getSkinPath(), _filename));
+ in = WFOPEN(file, WF_READONLY_BINARY);
+ }
+
+#if 0 // this isn't used in gen_ff, basically makes it look in C:/Program Files/Winamp/Skins/Default/
+ if (in == OPEN_FAILED)
+ {
+ file.swap(StringPathCombine(Skin::getDefaultSkinPath(), _filename));
+ in = WFOPEN(file, WF_READONLY_BINARY);
+ }
+#endif
+
+ // look in the fallback stuff (in Winamp5, this is c:/program files/winamp/plugins/freeform/xml)
+ if (in == OPEN_FAILED)
+ {
+ file.swap(StringPathCombine(g_resourcepath, _filename));
+ in = WFOPEN(file, WF_READONLY_BINARY);
+ }
+#endif
+
+ if (in == OPEN_FAILED && path)
+ {
+ in = WFOPEN(file = _filename, WF_READONLY_BINARY);
+ }
+
+ Wasabi::Std::setCurDir(olddir);
+
+ if (in != OPEN_FAILED)
+ {
+ int filelen = (int)FGETSIZE(in);
+ if (filelen > 0)
+ {
+ mem.setSize(filelen);
+ int len = FREAD(mem, 1, mem.getSizeInBytes(), in);
+ if (len == filelen)
+ {
+ svc_imageLoader *loader = ImgLoaderEnum(mem, len).getNext();
+ if (loader != NULL)
+ {
+ ret = loader->loadImage(mem, mem.getSizeInBytes(), w, h, params);
+ if (ret != NULL)
+ {
+ if (addMem)
+ addMemUsage(file, (*w) * (*h) * sizeof(ARGB32));
+ optimizeHasAlpha(ret, *w * *h, has_alpha);
+ }
+ SvcEnum::release(loader);
+ }
+ }
+ } // filelen > 0
+ FCLOSE(in);
+ } // if file opened
+ if (ret != NULL)
+ {
+ return ret;
+ }
+ else if (in != OPEN_FAILED && mem)
+ {
+ int m = getFileType(mem);
+#ifdef WIN32
+ switch (m)
+ {
+ case FT_BMP:
+ {
+ wchar_t tmpname[WA_MAX_PATH] = L"";
+
+ // FG> if loading bmp from disk, no need to do the copy to disk
+ HBITMAP hbmp = (HBITMAP)LoadImageW(0, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
+
+ if (!hbmp)
+ {
+ // CT> extract/copy the file into temp directory (so we don't have any trouble if the file
+ // is in a ZIP file). this whole copying thing will go away as soon as we'll get rid of
+ // the LoadImage win32 function and use our own bmp loading functions
+
+ GetTempPathW(WA_MAX_PATH, tmpname);
+ wcscat(tmpname, L"wa3tmp");
+ OSFILETYPE fs = WFOPEN(file, WF_READONLY_BINARY);
+ if (fs != OPEN_FAILED)
+ {
+ OSFILETYPE fd = WFOPEN(tmpname, L"wb");
+ int l;
+ do
+ {
+ char buf[1024] = {0};
+ l = FREAD(buf, 1, sizeof(buf), fs);
+ if (l > 0) FWRITE(buf, 1, l, fd);
+ }
+ while (l > 0);
+ FCLOSE(fs);
+ FCLOSE(fd);
+ hbmp = (HBITMAP)LoadImageW(0, tmpname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
+ }
+ if (!hbmp)
+ {
+#ifdef WASABI_COMPILE_SKIN_WA2
+ // bitmap not found or broken (like in the netscape skin)
+ // try to find it in the Classic skin (wa2)
+ StringW wa2skinFn = WASABI_API_APP->getSkinsPath();
+ wa2skinFn.AppendPath("Classic");
+ wa2skinFn.AppendPath(_filename);
+ fs = WFOPEN(wa2skinFn), WF_READONLY_BINARY);
+ if (fs != OPEN_FAILED)
+ {
+ OSFILETYPE fd = WFOPEN(tmpname, L"wb");
+ int l;
+ do
+ {
+ char buf[1024] = {0};
+ l = FREAD(buf, 1, sizeof(buf), fs);
+ if (l > 0) FWRITE(buf, 1, l, fd);
+ }
+ while (l > 0);
+ FCLOSE(fs);
+ FCLOSE(fd);
+ hbmp = (HBITMAP)LoadImageW(0, tmpname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
+ }
+#endif //WASABI_COMPILE_SKIN_WA2
+ }
+ if (!hbmp)
+ {
+ // no luck :(
+ _wunlink(tmpname);
+ return 0;
+ }
+ }
+
+ BITMAP bm;
+ HDC hMemDC, hMemDC2;
+ HBITMAP hprev, hprev2;
+ HBITMAP hsrcdib;
+ void *srcdib;
+ BITMAPINFO srcbmi = {0, };
+ int r = GetObject(hbmp, sizeof(BITMAP), &bm);
+ ASSERT(r != 0);
+ *w = bm.bmWidth;
+ *h = ABS(bm.bmHeight);
+
+ ARGB32 *newbits;
+ srcbmi.bmiHeader.biSize = sizeof(srcbmi.bmiHeader);
+ srcbmi.bmiHeader.biWidth = *w;
+ srcbmi.bmiHeader.biHeight = -*h;
+ srcbmi.bmiHeader.biPlanes = 1;
+ srcbmi.bmiHeader.biBitCount = 32;
+ srcbmi.bmiHeader.biCompression = BI_RGB;
+
+ hMemDC = CreateCompatibleDC(NULL);
+ hMemDC2 = CreateCompatibleDC(NULL);
+ hsrcdib = CreateDIBSection(hMemDC, &srcbmi, DIB_RGB_COLORS, &srcdib, NULL, 0);
+ ASSERTPR(hsrcdib != 0, "CreateDIBSection() failed #69");
+ hprev2 = (HBITMAP) SelectObject(hMemDC2, hbmp);
+ hprev = (HBITMAP) SelectObject(hMemDC, hsrcdib);
+ BitBlt(hMemDC, 0, 0, *w, *h, hMemDC2, 0, 0, SRCCOPY);
+ newbits = (ARGB32*)MALLOC((*w) * (*h) * sizeof(ARGB32));
+ MEMCPY32(newbits, srcdib, (*w)*(*h) /**sizeof(ARGB32)*/);
+ {
+ // put the alpha channel to 255
+ unsigned char *b = (unsigned char *)newbits;
+ int l = (*w) * (*h);
+ for (int i = 0;i < l;i++)
+ b[(i*4) + 3] = 0xff;
+ }
+ SelectObject(hMemDC, hprev);
+ SelectObject(hMemDC2, hprev2);
+ DeleteObject(hsrcdib);
+ DeleteDC(hMemDC2);
+ DeleteDC(hMemDC);
+
+ DeleteObject(hbmp);
+
+ if (tmpname[0])
+ _wunlink(tmpname); // destroy temp extraction
+
+ if (addMem)
+ addMemUsage(file, (*w)*(*h)*4);
+ return newbits;
+ }
+ }
+#endif
+ }
+ return ret;
+}
+
+int imageLoader::getFileType(unsigned char *pData)
+{
+ // Bmp ?
+#ifdef WIN32
+ WINBITMAPFILEHEADER * pBFH;
+ pBFH = (WINBITMAPFILEHEADER *) pData;
+#ifdef _WINDOWS
+ if (pBFH->bfType == 0x4d42)
+#else
+ if (pBFH->bfType == 0x424d)
+#endif
+ return FT_BMP;
+#endif
+ return FT_UNKNOWN;
+}
+
+#ifdef WASABI_COMPILE_SKIN
+
+ARGB32 *imageLoader::requestSkinBitmap(const wchar_t *id, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached)
+{
+ ifc_xmlreaderparams *params = NULL;
+ const wchar_t *rootpath = NULL;
+
+ const wchar_t *aliastarget = WASABI_API_PALETTE->getElementAlias(id);
+
+ if (aliastarget)
+ id = aliastarget;
+
+ const wchar_t *efile = WASABI_API_PALETTE->getSkinBitmapFilename(id, x, y, subw, subh, &rootpath, &params);
+
+ if (x && *x == -1) *x = 0;
+ if (y && *y == -1) *y = 0;
+
+ if (!efile)
+ efile = id;
+
+ if (cached)
+ {
+ StringPathCombine f(rootpath, efile);
+ f.toupper();
+ f.FixSlashes();
+
+ int pos = -1;
+ /*skinCacheEntry *entry = */skinCacheList.findItem(f.getValue(), &pos);
+ if (pos != -1)
+ {
+ //find first one
+ while (pos > 0 && !wcscmp(skinCacheList[pos - 1]->fullpathfilename, f)) pos--;
+ do
+ {
+ skinCacheEntry *entry = skinCacheList[pos];
+ if (GammaMgr::gammaEqual(entry->original_element_id, id) && layerEqual(entry->original_element_id, id))
+ {
+ entry->usageCount++;
+ if (w) *w = entry->width;
+ if (h) *h = entry->height;
+ if (has_alpha) *has_alpha = entry->has_alpha;
+ return entry->bitmapbits;
+ }
+ pos++;
+ if (pos >= skinCacheList.getNumItems()) break;
+ }
+ while (!wcscmp(skinCacheList[pos]->fullpathfilename, f));
+ }
+ }
+
+ int force_nocache = 0;
+ int t_has_alpha = 0;
+ ARGB32 *bits = makeBmp(efile, rootpath, &t_has_alpha, w, h, params, TRUE, &force_nocache);
+ if (has_alpha != NULL) *has_alpha = t_has_alpha;
+
+ if (!bits)
+ return NULL;
+
+ if (force_nocache || !cached) return bits;
+
+ skinCacheEntry *cachedbmp = new skinCacheEntry;
+
+ if (params)
+ {
+ for (size_t i = 0;i != params->getNbItems();i++)
+ cachedbmp->params.addItem(params->getItemName(i), params->getItemValue(i));
+ }
+
+ cachedbmp->usageCount = 1;
+ cachedbmp->bitmapbits = bits;
+ cachedbmp->filename = efile;
+ cachedbmp->has_alpha = !!t_has_alpha;
+ cachedbmp->width = *w;
+ cachedbmp->height = *h;
+ cachedbmp->original_element_id = id;
+
+ //needed for findItem above
+ StringPathCombine b(rootpath, efile);
+ b.toupper();
+ b.FixSlashes();
+ cachedbmp->fullpathfilename.swap(b);
+
+ applySkinFilters(cachedbmp);
+ skinCacheList.addItem(cachedbmp);
+
+ return cachedbmp->bitmapbits;
+}
+/*
+int imageLoader::paramsMatch(ifc_xmlreaderparams *a, ifc_xmlreaderparams *b)
+{
+ if (!a && !b) return 1;
+ if ((!a && b) || (!b && a)) return 0;
+ for (int i = 0;i < a->getNbItems();i++)
+ {
+ const wchar_t *name = a->getItemName(i);
+ if (!_wcsicmp(name, L"w") || !_wcsicmp(name, L"h") || !_wcsicmp(name, L"x") || !_wcsicmp(name, L"y")) continue;
+ if (_wcsicmp(a->getItemValue(i), b->getItemValue(name)))
+ return 0;
+ }
+ return 1;
+}
+*/
+int imageLoader::layerEqual(const wchar_t *id1, const wchar_t *id2)
+{
+ int a = WASABI_API_PALETTE->getLayerFromId(id1);
+ int b = WASABI_API_PALETTE->getLayerFromId(id2);
+ return (a == b);
+}
+
+void imageLoader::releaseSkinBitmap(ARGB32 *bitmapbits)
+{ //FG
+ int i;
+ // TODO: add critical sections
+
+ int ni = skinCacheList.getNumItems();
+ for (i = 0;i < ni;i++)
+ {
+ skinCacheEntry *entry = skinCacheList.enumItem(i);
+ if (entry->bitmapbits == bitmapbits)
+ {
+ entry->usageCount--;
+ if (entry->usageCount == 0)
+ {
+ subMemUsage(entry->width*entry->height*sizeof(int));
+ WASABI_API_MEMMGR->sysFree(entry->bitmapbits);
+ skinCacheList.removeByPos(i);
+ delete entry;
+ if (skinCacheList.getNumItems() == 0) skinCacheList.removeAll();
+ }
+ return ;
+ }
+ }
+ // bitmap was not a cached skin bitmap, simply free it
+ release(bitmapbits);
+}
+
+#endif //WASABI_COMPILE_SKIN
+
+void imageLoader::release(ARGB32 *bitmapbits)
+{
+ WASABI_API_MEMMGR->sysFree(bitmapbits);
+}
+
+void imageLoader::optimizeHasAlpha(ARGB32 *bits, int len, int *has_alpha)
+{
+ if (len <= 0 || has_alpha == NULL) return ;
+ for (*has_alpha = 0; len; len--, bits++)
+ {
+ ARGB32 v = *bits;
+ unsigned int alpha = v >> 24;
+ if (alpha != 255)
+ {
+ *has_alpha = 1;
+ break;
+ }
+ }
+}
+
+#ifdef WASABI_COMPILE_SKIN
+
+void imageLoader::applySkinFilters()
+{ //FG
+ int i;
+
+ Skin::unloadResources();
+ for (i = 0; i < skinCacheList.getNumItems(); i++)
+ {
+ skinCacheEntry *entry = skinCacheList.q(i);
+ applySkinFilters(entry);
+ }
+
+ WASABI_API_PALETTE->newSkinPart();
+ Skin::reloadResources();
+}
+
+void imageLoader::applySkinFilters(skinCacheEntry *entry)
+{
+ ASSERT(entry != NULL);
+
+ int w = entry->width, h = entry->height;
+
+ ApplySkinFilters::apply(entry->original_element_id, NULL, (ARGB32*)entry->bitmapbits, w, h);
+}
+
+ARGB32 imageLoader::filterSkinColor(ARGB32 color, const wchar_t *element_id, const wchar_t *groupname)
+{
+ SkinFilterEnum sfe;
+
+ svc_skinFilter *obj;
+ while (1)
+ {
+ obj = sfe.getNext(FALSE);
+ if (!obj) break;
+ color = obj->filterColor(color, element_id, groupname);
+ sfe.getLastFactory()->releaseInterface(obj);
+ }
+
+ return color;
+}
+
+#endif //WASABI_COMPILE_SKIN
+
+void imageLoader::addMemUsage(const wchar_t *filename, int size)
+{
+ totalMemUsage += size;
+#ifdef DEBUG_OUTPUT
+ DebugStringW("Bitmaps memory usage : %s - %d\n", filename, totalMemUsage);
+#endif
+}
+
+void imageLoader::subMemUsage(int size)
+{
+ totalMemUsage -= size;
+}
+
+#ifdef WASABI_COMPILE_SKIN
+
+//PtrList<skinCacheEntry> imageLoader::skinCacheList;
+PtrListInsertMultiSorted<skinCacheEntry, skinCacheComp> imageLoader::skinCacheList;
+#endif //WASABI_COMPILE_SKIN
+
+int imageLoader::totalMemUsage = 0; \ No newline at end of file
diff --git a/Src/Wasabi/api/imgldr/imgldr.h b/Src/Wasabi/api/imgldr/imgldr.h
new file mode 100644
index 00000000..33a64864
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imgldr.h
@@ -0,0 +1,86 @@
+#ifndef __IMGLDR_H
+#define __IMGLDR_H
+
+//CUT
+#define FT_UNKNOWN 0
+#define FT_BMP 1
+#define FT_JPEG 5
+#define FT_PNG 6
+
+#include <bfc/ptrlist.h>
+#include <tataki/bitmap/bitmap.h>
+#ifdef WASABI_COMPILE_XMLPARSER
+#include <api/xml/xmlreader.h>
+#include <api/xml/xmlparamsi.h>
+#else
+class XmlReaderParamsI;
+#endif
+#ifdef WASABI_COMPILE_SKIN
+#include <api/skin/skin.h>
+#include <api/skin/skinfilter.h>
+#endif
+
+#include <bfc/string/StringW.h>
+
+typedef struct {
+ ARGB32 *bitmapbits;
+ StringW filename;
+ int usageCount;
+ bool has_alpha;
+ int width;
+ int height;
+ StringW includepath;
+// String rootpath;
+ XmlReaderParamsI params;
+ StringW original_element_id;
+ StringW fullpathfilename;
+} skinCacheEntry;
+
+typedef unsigned long ARGB32;
+
+#ifdef WASABI_COMPILE_SKIN
+
+class skinCacheComp
+{
+public:
+ static int compareItem(void *p1, void *p2) {
+ return wcscmp(((skinCacheEntry *)p1)->fullpathfilename, ((skinCacheEntry *)p2)->fullpathfilename);
+ }
+ static int compareAttrib(const wchar_t *attrib, void *item) {
+ return wcscmp(attrib, ((skinCacheEntry *)item)->fullpathfilename);
+ }
+};
+
+#endif //WASABI_COMPILE_SKIN
+
+class imageLoader
+{
+public:
+ static ARGB32 *makeBmp(const wchar_t *filename, const wchar_t *path, int *has_alpha, int *w, int *h, ifc_xmlreaderparams *params, bool addmem, int *force_nocache);
+#ifdef _WIN32
+ static ARGB32 *makeBmp(OSMODULEHANDLE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *forcegroup=NULL);
+#endif
+ static int getFileType(uint8_t *pData);
+ static StringW getWallpaper();
+ static void release(ARGB32 *bitmapbits);
+#ifdef WASABI_COMPILE_SKIN
+ static ARGB32 *requestSkinBitmap(const wchar_t *id, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached=1);
+ static void releaseSkinBitmap(ARGB32 *bmpbits);
+ static void applySkinFilters();
+ static void applySkinFilters(skinCacheEntry *entry);
+ static ARGB32 filterSkinColor(ARGB32 color, const wchar_t *elementid, const wchar_t *groupname);
+ static int layerEqual(const wchar_t *id1, const wchar_t *id2);
+#endif //WASABI_COMPILE_SKIN
+ static int getMemUsage() { return totalMemUsage; }
+ static int getNumCached() { return skinCacheList.getNumItems(); }
+private:
+#ifdef WASABI_COMPILE_SKIN
+ //static int paramsMatch(ifc_xmlreaderparams *a, ifc_xmlreaderparams *b);
+ static PtrListInsertMultiSorted<skinCacheEntry,skinCacheComp> skinCacheList;
+#endif //WASABI_COMPILE_SKIN
+ static void optimizeHasAlpha(ARGB32 *bits, int len, int *has_alpha);
+ static void addMemUsage(const wchar_t *filename, int size);
+ static void subMemUsage(int size);
+ static int totalMemUsage;
+};
+#endif
diff --git a/Src/Wasabi/api/imgldr/imgldrapi.cpp b/Src/Wasabi/api/imgldr/imgldrapi.cpp
new file mode 100644
index 00000000..45790615
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imgldrapi.cpp
@@ -0,0 +1,81 @@
+#include "precomp.h"
+#include <api.h>
+#include "imgldrapi.h"
+#include <api/imgldr/imgldr.h>
+
+#include <api/skin/skinelem.h>
+imgldr_api *imgLoaderApi = NULL;
+
+ARGB32 *ImgLdrApi::imgldr_makeBmp(const wchar_t *filename, int *has_alpha, int *w, int *h)
+{
+ if (filename == NULL)
+ {
+ DebugString("illegal param : filename == NULL");
+ return NULL;
+ }
+ return imageLoader::makeBmp(filename, NULL, has_alpha, w, h, NULL, TRUE, NULL);
+}
+
+#ifdef _WIN32
+ARGB32 *ImgLdrApi::imgldr_makeBmp2(HINSTANCE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *colorgroup)
+{
+ return imageLoader::makeBmp(hInst, id, has_alpha,w,h, colorgroup);
+}
+#endif
+
+void ImgLdrApi::imgldr_releaseBmp(ARGB32 *bmpbits)
+{
+ if (bmpbits == NULL) {
+ DebugString("illegal param : bmpbits == NULL");
+ return;
+ }
+ imageLoader::release(bmpbits);
+}
+
+#ifdef WASABI_COMPILE_SKIN
+
+ARGB32 *ImgLdrApi::imgldr_requestSkinBitmap(const wchar_t *file, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached)
+{
+ if (file == NULL)
+ {
+ DebugString("illegal param : file == NULL");
+ return NULL;
+ }
+ return imageLoader::requestSkinBitmap(file, has_alpha, x, y, subw, subh, w, h, cached);
+}
+
+void ImgLdrApi::imgldr_releaseSkinBitmap(ARGB32 *bmpbits)
+{
+ if (bmpbits == NULL)
+ {
+ DebugString("illegal param : bmpbits == NULL");
+ return;
+ }
+ imageLoader::releaseSkinBitmap(bmpbits);
+}
+
+RegionServer *ImgLdrApi::imgldr_requestSkinRegion(const wchar_t *id)
+{
+ if (id == NULL)
+ {
+ DebugString("illegal param : id == NULL");
+ return NULL;
+ }
+ return WASABI_API_PALETTE->requestSkinRegion(id);
+}
+
+void ImgLdrApi::imgldr_cacheSkinRegion(const wchar_t *id, api_region *r)
+{
+ if (id == NULL)
+ {
+ DebugString("illegal param : id == NULL");
+ }
+ if (r == NULL)
+ {
+ DebugString("illegal param : region == NULL");
+ }
+ WASABI_API_PALETTE->cacheSkinRegion(id, r);
+}
+
+#endif
+
diff --git a/Src/Wasabi/api/imgldr/imgldrapi.h b/Src/Wasabi/api/imgldr/imgldrapi.h
new file mode 100644
index 00000000..b94fdfa5
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/imgldrapi.h
@@ -0,0 +1,23 @@
+#ifndef __IMGLDRAPI_H
+#define __IMGLDRAPI_H
+
+#include <api/imgldr/api_imgldr.h>
+
+class ImgLdrApi : public imgldr_apiI
+{
+ public:
+ ARGB32 *imgldr_makeBmp(const wchar_t *filename, int *has_alpha, int *w, int *h);
+#ifdef _WIN32
+ ARGB32 *imgldr_makeBmp2(OSMODULEHANDLE hInst, int id, int *has_alpha, int *w, int *h, const wchar_t *colorgroup = NULL);
+#endif
+ void imgldr_releaseBmp(ARGB32 *bmpbits);
+#ifdef WASABI_COMPILE_SKIN
+ ARGB32 *imgldr_requestSkinBitmap(const wchar_t *file, int *has_alpha, int *x, int *y, int *subw, int *subh, int *w, int *h, int cached);
+ RegionServer *imgldr_requestSkinRegion(const wchar_t *id);
+ void imgldr_cacheSkinRegion(const wchar_t *id, api_region *r);
+ void imgldr_releaseSkinBitmap(ARGB32 *bmpbits);
+#endif //WASABI_COMPILE_SKIN
+};
+
+
+#endif
diff --git a/Src/Wasabi/api/imgldr/skinbmps.h b/Src/Wasabi/api/imgldr/skinbmps.h
new file mode 100644
index 00000000..dab8568c
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/skinbmps.h
@@ -0,0 +1,122 @@
+#ifndef _SKINBMPS_H
+#define _SKINBMPS_H
+/*
+typedef enum {
+ SKIN_BITMAP_UNKNOWN,
+
+ // Base texture
+ SKIN_BITMAP_BASE_TEXTURE,
+
+ // Framewnd
+ SKIN_BITMAP_FRAME_VERTICAL_DIVIDER,
+ SKIN_BITMAP_FRAME_HORIZONTAL_DIVIDER,
+
+ // Listwnd/Treewnd
+ SKIN_BITMAP_LIST_BACKGROUND,
+ SKIN_BITMAP_TREE_BACKGROUND,
+
+ // Appctrl
+ SKIN_BITMAP_APPCTRL_LEFTARROW_NONPRESSED,
+ SKIN_BITMAP_APPCTRL_LEFTARROW_PRESSED,
+ SKIN_BITMAP_APPCTRL_RIGHTARROW_NONPRESSED,
+ SKIN_BITMAP_APPCTRL_RIGHTARROW_PRESSED,
+ SKIN_BITMAP_APPCTRL_WINDOWSIZER,
+ SKIN_BITMAP_APPCTRL_PLAYERMODE_NONPRESSED,
+ SKIN_BITMAP_APPCTRL_PLAYERMODE_PRESSED,
+ SKIN_BITMAP_APPCTRL_MINIMIZE_NONPRESSED,
+ SKIN_BITMAP_APPCTRL_MINIMIZE_PRESSED,
+ SKIN_BITMAP_APPCTRL_MAXIMIZE_NONPRESSED,
+ SKIN_BITMAP_APPCTRL_MAXIMIZE_PRESSED,
+ SKIN_BITMAP_APPCTRL_CLOSE_NONPRESSED,
+ SKIN_BITMAP_APPCTRL_CLOSE_PRESSED,
+ SKIN_BITMAP_APPCTRL_SYSTEMICON,
+ SKIN_BITMAP_APPCTRL_PLACEHOLDER_LEFT,
+ SKIN_BITMAP_APPCTRL_PLACEHOLDER_MIDDLE,
+ SKIN_BITMAP_APPCTRL_PLACEHOLDER_RIGHT,
+ SKIN_BITMAP_APPCTRL_TITLEBAR,
+
+ // Controls
+ SKIN_BITMAP_PLAYBACKCONTROLS_PREVIOUS_NONPRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_PREVIOUS_PRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_PLAY_NONPRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_PLAY_PRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_PAUSE_NONPRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_PAUSE_PRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_STOP_NONPRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_STOP_PRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_NEXT_NONPRESSED,
+ SKIN_BITMAP_PLAYBACKCONTROLS_NEXT_PRESSED,
+
+ // Paintset
+ SKIN_BITMAP_LABEL_UPPERLEFT,
+ SKIN_BITMAP_LABEL_TOP,
+ SKIN_BITMAP_LABEL_UPPERRIGHT,
+ SKIN_BITMAP_LABEL_LEFT,
+ SKIN_BITMAP_LABEL_MIDDLE,
+ SKIN_BITMAP_LABEL_RIGHT,
+ SKIN_BITMAP_LABEL_LOWERLEF,
+ SKIN_BITMAP_LABEL_BOTTOM,
+ SKIN_BITMAP_LABEL_LOWERRIGHT,
+ SKIN_BITMAP_APPBORDER_UPPERLEFT,
+ SKIN_BITMAP_APPBORDER_TOP,
+ SKIN_BITMAP_APPBORDER_UPPERRIGHT,
+ SKIN_BITMAP_APPBORDER_LEFT,
+ SKIN_BITMAP_APPBORDER_RIGHT,
+ SKIN_BITMAP_APPBORDER_LOWERLEFT,
+ SKIN_BITMAP_APPBORDER_BOTTOM,
+ SKIN_BITMAP_APPBORDER_LOWERRIGHT,
+
+ // Seeker
+ SKIN_BITMAP_SEEKBAR_LEFT,
+ SKIN_BITMAP_SEEKBAR_MIDDLE,
+ SKIN_BITMAP_SEEKBAR_RIGHT,
+ SKIN_BITMAP_SEEKBAR_BUTTON_NONPRESSED,
+ SKIN_BITMAP_BUTTON_PRESSED,
+
+ // Status
+ SKIN_BITMAP_STATUSBAR_LEFT,
+ SKIN_BITMAP_STATUSBAR_MIDDLE,
+ SKIN_BITMAP_STATUSBAR_RIGHT,
+
+ // Volbar
+ SKIN_BITMAP_VOLBAR_LEFT,
+ SKIN_BITMAP_VOLBAR_MIDDLE,
+ SKIN_BITMAP_VOLBAR_RIGHT,
+ SKIN_BITMAP_VOLBAR_BUTTON_NONPRESSED,
+ SKIN_BITMAP_VOLBAR_BUTTON_PRESSED,
+
+ // Titlewnd
+ SKIN_BITMAP_COMPONENT_PROP_TOP,
+ SKIN_BITMAP_COMPONENT_PROP,
+ SKIN_BITMAP_COMPONENT_PROP_MIDDLE,
+ SKIN_BITMAP_COMPONENT_PROP_BOTTOM,
+
+ // Videownd
+ SKIN_BITMAP_MOVIE_BACKGROUND,
+
+ // Seditwnd
+ SKIN_BITMAP_AVS_SCRIPT_MARKER,
+ SKIN_BITMAP_AVS_SCRIPT_PLAY_NONPRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_PLAY_PRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_PAUSE_NONPRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_PAUSE_PRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_STOP_NONPRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_STOP_PRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_TIMEARROW,
+ SKIN_BITMAP_AVS_SCRIPT_BACKGROUND,
+ SKIN_BITMAP_AVS_SCRIPT_ZOOMER_TOP,
+ SKIN_BITMAP_AVS_SCRIPT_ZOOMER_MIDDLE,
+ SKIN_BITMAP_AVS_SCRIPT_ZOOMER_BOTTOM,
+ SKIN_BITMAP_AVS_SCRIPT_ZOOMER_BUTTON_NONPRESSED,
+ SKIN_BITMAP_AVS_SCRIPT_ZOOMER_BUTTON_PRESSED,
+
+// ComponentAPI1 ends here
+ NUM_SKIN_BITMAP_ELEMENT_IDS
+} SkinBitmapElementId;
+
+typedef struct {
+ SkinBitmapElementId id;
+ char *fn;
+ } SkinBitmapTableElement;
+*/
+#endif
diff --git a/Src/Wasabi/api/imgldr/winbmp.h b/Src/Wasabi/api/imgldr/winbmp.h
new file mode 100644
index 00000000..afcc0784
--- /dev/null
+++ b/Src/Wasabi/api/imgldr/winbmp.h
@@ -0,0 +1,47 @@
+#ifndef __WINBMP_H
+#define __WINBMP_H
+
+typedef struct tagWINRGBQUAD
+{
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+ BYTE rgbReserved;
+} WINRGBQUAD;
+
+typedef struct tagWINBITMAPFILEHEADER
+{
+ WORD bfType;
+ LONG bfSize;
+ WORD bfReserved1;
+ WORD bfReserved2;
+ LONG bfOffBits;
+} WINBITMAPFILEHEADER;
+
+typedef struct tagWINBITMAPINFOHEADER
+{
+ LONG biSize;
+ LONG biWidth;
+ LONG biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+ LONG biCompression;
+ LONG biSizeImage;
+ LONG biXPelsPerMeter;
+ LONG biYPelsPerMeter;
+ LONG biClrUsed;
+ LONG biClrImportant;
+} WINBITMAPINFOHEADER;
+
+typedef struct tagWINBITMAPINFO
+{
+ WINBITMAPINFOHEADER bmiHeader;
+ WINRGBQUAD bmiColors[1];
+} WINBITMAPINFO;
+
+#define BI_RGB 0L
+#define BI_RLE8 1L
+#define BI_RLE4 2L
+#define BI_BITFIELDS 3L
+
+#endif