aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/platform
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/wnd/platform
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/platform')
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/PaintCanvas.cpp51
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/PaintCanvas.h45
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/bltcanvas.h26
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/canvas.h69
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.cpp220
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.h47
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/osx_canvas_layer.cpp95
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/osx_canvas_quartz.cpp275
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/osx_region_hishape.cpp217
-rw-r--r--Src/Wasabi/api/wnd/platform/osx/region.h115
-rw-r--r--Src/Wasabi/api/wnd/platform/win32/bitmap.h81
-rw-r--r--Src/Wasabi/api/wnd/platform/win32/canvas.h1
-rw-r--r--Src/Wasabi/api/wnd/platform/win32/region.h135
13 files changed, 1377 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/platform/osx/PaintCanvas.cpp b/Src/Wasabi/api/wnd/platform/osx/PaintCanvas.cpp
new file mode 100644
index 00000000..6cfeb126
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/PaintCanvas.cpp
@@ -0,0 +1,51 @@
+#include "PaintCanvas.h"
+
+PaintCanvas::PaintCanvas()
+{
+ qdcontext=0;
+}
+
+bool PaintCanvas::beginPaint(BaseWnd *wnd)
+{
+ HIWindowRef macWnd = wnd->getOsWindowHandle();
+
+ qdcontext = GetWindowPort(macWnd);
+ QDBeginCGContext(qdcontext, &context);
+
+ return true;
+}
+
+PaintCanvas::~PaintCanvas()
+{
+ if (qdcontext)
+ QDEndCGContext(qdcontext, &context);
+}
+
+WndCanvas::WndCanvas()
+{
+ qdcontext=0;
+}
+
+WndCanvas::~WndCanvas()
+{
+ if (qdcontext)
+ QDEndCGContext(qdcontext, &context);
+}
+
+int WndCanvas::attachToClient(BaseWnd *basewnd)
+{
+ HIWindowRef macWnd = basewnd->getOsWindowHandle();
+
+ qdcontext = GetWindowPort(macWnd);
+ QDBeginCGContext(qdcontext, &context);
+ return 1;
+}
+
+
+TextInfoCanvas::TextInfoCanvas(BaseWnd */*unused*/)
+{
+}
+
+TextInfoCanvas::~TextInfoCanvas()
+{
+}
diff --git a/Src/Wasabi/api/wnd/platform/osx/PaintCanvas.h b/Src/Wasabi/api/wnd/platform/osx/PaintCanvas.h
new file mode 100644
index 00000000..f9091404
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/PaintCanvas.h
@@ -0,0 +1,45 @@
+#ifndef NULLSOFT_WASABI_OSX_PAINTCANVAS_H
+#define NULLSOFT_WASABI_OSX_PAINTCANVAS_H
+
+#include <tataki/canvas/canvas.h>
+#include <api/wnd/basewnd.h>
+
+class PaintCanvas : public Canvas
+{
+public:
+ PaintCanvas();
+ ~PaintCanvas();
+ bool beginPaint(BaseWnd *wnd);
+protected:
+ CGrafPtr qdcontext;
+};
+
+class PaintBltCanvas : public PaintCanvas
+{
+public:
+ bool beginPaintNC(BaseWnd *wnd)
+ {
+ return beginPaint(wnd);
+ }
+};
+#warning port PaintBltCanvas
+class WndCanvas : public Canvas
+{
+public:
+ WndCanvas();
+ virtual ~WndCanvas();
+
+ // address client area
+ int attachToClient(BaseWnd *basewnd);
+
+private:
+ CGrafPtr qdcontext;
+};
+
+class TextInfoCanvas : public Canvas
+{
+public:
+ TextInfoCanvas(BaseWnd *baseWnd);
+ virtual ~TextInfoCanvas();
+};
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/wnd/platform/osx/bltcanvas.h b/Src/Wasabi/api/wnd/platform/osx/bltcanvas.h
new file mode 100644
index 00000000..399deb71
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/bltcanvas.h
@@ -0,0 +1,26 @@
+#ifndef _BLTCANVAS_H
+#define _BLTCANVAS_H
+
+#include "canvas.h"
+
+class BltCanvas : public Canvas
+{
+public:
+ BltCanvas();
+ BltCanvas(int width, int height, OSWINDOWHANDLE wnd);
+
+ // override blit and stretchblit so we can use CGContextDrawLayerAtPoint/CGContextDrawLayerInRect
+ virtual void blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth);
+ void blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha = 255);
+
+ virtual void stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth);
+ void stretchToRectAlpha(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha = 255);
+
+ void DestructiveResize(int w, int h, int nb_bpp = 32); // resizes the bitmap, destroying the contents
+ void fillBits(ARGB32 color);
+
+protected:
+ CGLayerRef layer;
+};
+
+#endif
diff --git a/Src/Wasabi/api/wnd/platform/osx/canvas.h b/Src/Wasabi/api/wnd/platform/osx/canvas.h
new file mode 100644
index 00000000..9a434026
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/canvas.h
@@ -0,0 +1,69 @@
+#ifndef NULLSOFT_WASABI_CANVAS_H
+#define NULLSOFT_WASABI_CANVAS_H
+
+#include <Carbon/Carbon.h>
+#include <tataki/canvas/ifc_canvas.h>
+#include <bfc/platform/platform.h>
+#include <api/service/svcs/svc_font.h> // for STDFONT_* stuff. should make a std_font thingy later
+#include <bfc/std.h> // for WASABI_DEFAULT_FONTNAMEW
+class BaseWnd;
+class api_region;
+
+class Canvas : public ifc_canvas
+{
+public:
+ Canvas() :context(0), wnd(0) {}
+ Canvas(CGContextRef _context) : context(_context), wnd(0) {}
+ Canvas(CGrafPtr _context);
+ HDC getHDC();
+ void fillRect(const RECT *r, RGB32 color);
+ void fillRgn(api_region *r, RGB32 color);
+ void setBaseWnd(BaseWnd *_wnd) { wnd=_wnd; }
+ void selectClipRgn(api_region *r);
+
+ virtual void blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth);
+ virtual void stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth);
+
+ void textOut(int x, int y, const wchar_t *txt, const Wasabi::FontInfo *fontInfo);
+
+ static float getSystemFontScale() { return 1.0f; }
+
+ int getTextWidth(const wchar_t *text, const Wasabi::FontInfo *fontInfo);
+ int getTextHeight(const wchar_t *text, const Wasabi::FontInfo *fontInfo);
+ int getTextHeight(const Wasabi::FontInfo *fontInfo)
+ {
+ return getTextHeight(L"M", fontInfo);
+ }
+ void getTextExtent(const wchar_t *text, int *w, int *h, const Wasabi::FontInfo *fontInfo);
+ void textOutCentered(RECT *r, const wchar_t *txt, const Wasabi::FontInfo *fontInfo);
+ void textOut(int x, int y, int w, int h, const wchar_t *txt, const Wasabi::FontInfo *fontInfo);
+ void textOutEllipsed(int x, int y, int w, int h, const wchar_t *txt, const Wasabi::FontInfo *fontInfo);
+
+ void drawSysObject(const RECT *r, int sysobj, int alpha=255);
+protected:
+ RECVS_DISPATCH;
+
+ CGContextRef context;
+ BaseWnd *wnd; // TODO: not 100% sure we'll need this. win32 version has it so we'll keep it for now
+};
+
+class BaseCloneCanvas : public Canvas
+{
+public:
+ BaseCloneCanvas(ifc_canvas *cloner=NULL);
+ virtual ~BaseCloneCanvas();
+
+ int clone(ifc_canvas *cloner);
+};
+
+namespace DrawSysObj {
+ enum {
+ BUTTON, BUTTON_PUSHED, BUTTON_DISABLED,
+ OSBUTTON, OSBUTTON_PUSHED, OSBUTTON_DISABLED,
+ OSBUTTON_CLOSE, OSBUTTON_CLOSE_PUSHED, OSBUTTON_CLOSE_DISABLED,
+ OSBUTTON_MINIMIZE, OSBUTTON_MINIMIZE_PUSHED, OSBUTTON_MINIMIZE_DISABLED,
+ OSBUTTON_MAXIMIZE, OSBUTTON_MAXIMIZE_PUSHED, OSBUTTON_MAXIMIZE_DISABLED,
+ };
+};
+
+#endif
diff --git a/Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.cpp b/Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.cpp
new file mode 100644
index 00000000..fe9f3363
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.cpp
@@ -0,0 +1,220 @@
+#include "osx_bitmap_cgimage.h"
+
+SkinBitmap::SkinBitmap(ARGB32 *_bits, int w, int h) : image(0)
+{
+ // TODO: allow a mechanism for SkinBitmap to take ownership of the data
+ bits = malloc(w*h*4);
+ if (bits)
+ {
+ memcpy(bits, _bits, w*h*4);
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ imageContext = CGBitmapContextCreate(bits, w, h, 8, w*4, colorSpace, kCGBitmapByteOrder32Little|kCGImageAlphaPremultipliedFirst);
+ image = CGBitmapContextCreateImage(imageContext);
+ CGColorSpaceRelease(colorSpace);
+ }
+}
+
+SkinBitmap::~SkinBitmap()
+{
+ CGImageRelease(image);
+#ifndef SKINBITMAP_USE_CGIMAGE
+ free(bits);
+ CGContextRelease(imageContext);
+#endif
+}
+
+#ifdef WASABI_COMPILE_IMGLDR
+SkinBitmap::SkinBitmap(const wchar_t *elementname, int _cached)
+{
+ ASSERT(elementname!= NULL);
+
+ bitmapname = elementname;
+ x_offset = -1;
+ y_offset = -1;
+ subimage_w = -1;
+ subimage_h = -1;
+ fullimage_w=fullimage_h=0;
+ ownbits=1;
+ fromskin = 0;
+ last_failed = 0;
+#ifdef WASABI_COMPILE_SKIN
+ bits = WASABI_API_IMGLDR->imgldr_requestSkinBitmap(elementname, &has_alpha, &x_offset, &y_offset, &subimage_w, &subimage_h, &fullimage_w, &fullimage_h,_cached);
+ fromskin = (bits != NULL);
+#else
+ bits = NULL;
+#endif
+ if (bits == NULL)
+ bits = WASABI_API_IMGLDR->imgldr_makeBmp(elementname, &has_alpha, &fullimage_w, &fullimage_h);
+#ifdef WASABI_COMPILE_SKIN
+ if (bits == NULL)
+ {
+ bits = WASABI_API_IMGLDR->imgldr_requestSkinBitmap(ERRORBMP, &has_alpha, &x_offset, &y_offset, &subimage_w, &subimage_h, &fullimage_w, &fullimage_h,_cached);
+ last_failed = 1;
+ }
+#endif
+ if (bits == NULL)
+ {
+ bits = WASABI_API_IMGLDR->imgldr_makeBmp(HARDERRORBMP, &has_alpha, &fullimage_w, &fullimage_h);
+ last_failed = 1;
+ }
+
+ // check that coordinates are correct
+ if(x_offset!=-1 && x_offset>fullimage_w) x_offset=fullimage_w-1;
+ if(y_offset!=-1 && y_offset>fullimage_h) y_offset=fullimage_h-1;
+ if(subimage_w!=-1 && (x_offset+subimage_w)>fullimage_w) subimage_w=fullimage_w-x_offset;
+ if(subimage_h!=-1 && (y_offset+subimage_h)>fullimage_h) subimage_h=fullimage_h-y_offset;
+
+ // ASSERTPR(bits != NULL, elementname);
+ if (bits == NULL) {
+ DebugString("element not found ! %s\n", elementname);
+ int n = 10*10;
+ bits = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc(n * 4);
+
+
+ ARGB32 *p = bits;
+ while (n--)
+ *p++ = 0xFFFF00FF;
+ }
+}
+#endif
+
+
+int SkinBitmap::getWidth()
+{
+ if (!image)
+ return 0;
+
+ return CGImageGetWidth(image);
+}
+
+int SkinBitmap::getFullWidth()
+{
+ if (!image)
+ return 0;
+
+ return CGImageGetBytesPerRow(image)/4; // assumes 32bit pixel data
+}
+
+int SkinBitmap::getHeight()
+{
+ if (!image)
+ return 0;
+ return CGImageGetHeight(image);
+}
+
+void SkinBitmap::blit(ifc_canvas *canvas, int x, int y)
+{
+ if (!image)
+ return;
+
+ CGContextRef context = canvas->getHDC();
+ CGRect rect = CGRectMake(x, y, getWidth(), getHeight());
+ CGContextDrawImage(context, rect, image);
+}
+
+void SkinBitmap::blitAlpha(ifc_canvas *canvas, int x, int y, int alpha)
+{
+ if (!image)
+ return;
+
+ float floatAlpha = alpha / 255.f;
+
+ CGContextRef context = canvas->getHDC();
+ CGContextSaveGState(context);
+
+// CGContextTranslateCTM(context, 0, r->bottom);
+// CGContextScaleCTM(context, 1.0, -1.0);
+
+ CGContextSetAlpha(context, floatAlpha);
+ CGRect rect = CGRectMake(x, y, getWidth(), getHeight());
+ CGContextDrawImage(context, rect, image);
+ CGContextRestoreGState(context);
+}
+
+void SkinBitmap::stretchToRect(ifc_canvas *canvas, RECT *r)
+{
+ if (!image)
+ return;
+
+ CGContextRef context = canvas->getHDC();
+ CGContextSaveGState(context);
+
+ CGContextTranslateCTM (context, 0, r->bottom);
+ CGContextScaleCTM(context, 1.0, -1.0);
+
+ CGRect rect = CGRectMake(r->left, r->top, r->right-r->left, r->bottom-r->top);
+ CGContextDrawImage(context, rect, image);
+
+ CGContextRestoreGState(context);
+}
+
+void SkinBitmap::stretchToRectAlpha(ifc_canvas *canvas, RECT *r, int alpha)
+{
+ if (!image)
+ return;
+
+ float floatAlpha = alpha / 255.f;
+
+ CGContextRef context = canvas->getHDC();
+ CGContextSaveGState(context);
+
+ CGContextTranslateCTM (context, 0, r->bottom);
+ CGContextScaleCTM(context, 1.0, -1.0);
+
+ CGContextSetAlpha(context, floatAlpha);
+ CGRect rect = CGRectMake(r->left, r->top, r->right-r->left, r->bottom-r->top);
+ CGContextDrawImage(context, rect, image);
+ CGContextRestoreGState(context);
+}
+
+void SkinBitmap::stretchToRectAlpha(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha)
+{
+ if (!image)
+ return;
+
+ float floatAlpha = alpha / 255.f;
+
+ // make a new image ref clipped to the source rect
+ CGRect srcRect = CGRectMake(src->left, src->top, src->right-src->left, src->bottom-src->top);
+ CGImageRef clippedImage = CGImageCreateWithImageInRect(image, srcRect);
+
+ // blit onto canvas
+ CGContextRef context = canvas->getHDC();
+ CGContextSaveGState(context);
+
+ CGContextTranslateCTM(context, 0, dst->bottom);
+ CGContextScaleCTM(context, 1.0, -1.0);
+
+ CGContextSetAlpha(context, floatAlpha);
+ CGRect rect = CGRectMake(dst->left, dst->top, dst->right-dst->left, dst->bottom-dst->top);
+ CGContextDrawImage(context, rect, clippedImage);
+ CGContextRestoreGState(context);
+
+ // release the reference to our clipped image
+ CGImageRelease(clippedImage);
+}
+
+uint8_t *SkinBitmap::getBits()
+{
+ return static_cast<uint8_t *>(CGBitmapContextGetData(imageContext));
+}
+
+void SkinBitmap::UpdateBits(uint8_t *bits)
+{
+ CGImageRelease(image);
+ image = CGBitmapContextCreateImage(imageContext);
+}
+
+ARGB32 SkinBitmap::getPixel(int x, int y)
+{
+ ARGB32 *array = (ARGB32 *)getBits();
+ return array[x + y*getFullWidth()];
+}
+
+#define CBCLASS SkinBitmap
+START_DISPATCH;
+CB(IFC_BITMAP_GETBITMAP, GetBitmap);
+CB(IFC_BITMAP_GETBITS, getBits);
+VCB(IFC_BITMAP_UPDATEBITS, UpdateBits);
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.h b/Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.h
new file mode 100644
index 00000000..5a30637e
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/osx_bitmap_cgimage.h
@@ -0,0 +1,47 @@
+#ifndef NULLSOFT_WASABI_OSX_BITMAP_CGIMAGE_H
+#define NULLSOFT_WASABI_OSX_BITMAP_CGIMAGE_H
+
+#include <bfc/platform/platform.h>
+#include <tataki/canvas/ifc_canvas.h>
+#include <api/wnd/ifc_bitmap.h>
+
+/*
+ TODO:
+ need some kind of updateBits() so that the underlying image can be updated to reflect changes
+ */
+class SkinBitmap : public ifc_bitmap
+{
+public:
+ SkinBitmap(ARGB32 *bits, int w, int h); // added by benski, use if you have raw image bits
+ SkinBitmap(const wchar_t *elementname, int cached = 1);
+ ~SkinBitmap();
+ int getWidth();
+ int getHeight();
+ int getFullWidth(); // aka pitch
+
+ // blits
+ void blit(ifc_canvas *canvas, int x, int y);
+ void blitAlpha(ifc_canvas *canvas, int x, int y, int alpha = 255);
+ // stretch blits
+ void stretchToRect(ifc_canvas *canvas, RECT *r);
+ void stretchToRectAlpha(ifc_canvas *canvas, RECT *r, int alpha = 255);
+ void stretchToRectAlpha(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha = 255);
+// tiled blits
+ void blitTile(ifc_canvas *canvas, RECT *dest, int xoffs = 0, int yoffs = 0, int alpha = 255);
+
+ ARGB32 getPixel(int x, int y);
+public: // ifc_bitmap implementations
+ OSBITMAPHANDLE GetBitmap() { return image; }
+ uint8_t *getBits();
+ void UpdateBits(uint8_t *bits);
+
+private:
+ CGImageRef image;
+ CGContextRef imageContext;
+ void *bits;
+
+protected:
+ RECVS_DISPATCH;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/wnd/platform/osx/osx_canvas_layer.cpp b/Src/Wasabi/api/wnd/platform/osx/osx_canvas_layer.cpp
new file mode 100644
index 00000000..43c2984b
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/osx_canvas_layer.cpp
@@ -0,0 +1,95 @@
+#include <tataki/canvas/bltcanvas.h>
+
+inline float QuartzBlue(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[0] / 255.f;
+}
+
+inline float QuartzGreen(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[1] / 255.f;
+}
+
+inline float QuartzRed(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[2] / 255.f;
+}
+
+inline float QuartzAlpha(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[3] / 255.f;
+}
+
+BltCanvas::BltCanvas(int width, int height, OSWINDOWHANDLE wnd)
+{
+ CGrafPtr qdcontext = GetWindowPort(wnd);
+ CGContextRef temp;
+ QDBeginCGContext(qdcontext, &temp);
+ CGSize size = CGSizeMake(width, height);
+ layer = CGLayerCreateWithContext(temp, size, NULL);
+ context = CGLayerGetContext(layer);
+ QDEndCGContext(qdcontext, &temp);
+}
+
+void BltCanvas::blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth)
+{
+ CGPoint point = CGPointMake(dstx-srcx, dsty-srcy);
+ CGContextDrawLayerAtPoint(dest->getHDC(), point, layer);
+}
+
+void BltCanvas::blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha)
+{
+ CGContextRef dest = canvas->getHDC();
+ CGContextSaveGState(dest);
+ CGContextSetAlpha(dest, (float)alpha/255.f);
+ // TODO: deal with width properly
+ CGRect rect = CGRectMake(dst->left - src->left, dst->top - src->top, dst->right - dst->left, dst->bottom - dst->top);
+ CGContextDrawLayerInRect(dest, rect, layer);
+ CGContextRestoreGState(dest);
+}
+
+void BltCanvas::stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth)
+{
+ CGContextSaveGState(context);
+ CGContextTranslateCTM(context, srcx, srcy);
+ CGRect rect = CGRectMake(dstx, dsty, dstw, dsth);
+ CGContextDrawLayerInRect(dest->getHDC(), rect, layer);
+ CGContextRestoreGState(context);
+}
+
+void BltCanvas::stretchToRectAlpha(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha)
+{
+ CGContextRef dest = canvas->getHDC();
+ CGContextSaveGState(dest);
+ CGContextSetAlpha(dest, (float)alpha/255.f);
+// TODO: deal with width properly
+ CGRect rect = CGRectMake(dst->left - src->left, dst->top - src->top, dst->right - dst->left, dst->bottom - dst->top);
+ CGContextDrawLayerInRect(dest, rect, layer);
+ CGContextRestoreGState(dest);
+}
+
+void BltCanvas::DestructiveResize(int w, int h, int nb_bpp)
+{
+ CGSize size = CGSizeMake(w, h);
+ CGLayerRef newlayer = CGLayerCreateWithContext(context, size, NULL);
+ CGContextRelease(context);
+ CGLayerRelease(layer);
+ layer = newlayer;
+ context = CGLayerGetContext(layer);
+}
+
+void BltCanvas::fillBits(ARGB32 color)
+{
+ CGContextSetRGBFillColor(context,
+ QuartzRed(color), // red
+ QuartzGreen(color), // green
+ QuartzBlue(color), // blue
+ QuartzAlpha(color) // alpha
+ );
+
+ CGContextFillRect(context, CGRectInfinite);
+} \ No newline at end of file
diff --git a/Src/Wasabi/api/wnd/platform/osx/osx_canvas_quartz.cpp b/Src/Wasabi/api/wnd/platform/osx/osx_canvas_quartz.cpp
new file mode 100644
index 00000000..093ab5e5
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/osx_canvas_quartz.cpp
@@ -0,0 +1,275 @@
+#include <bfc/platform/types.h>
+#include <Carbon/Carbon.h>
+#include <tataki/canvas/canvas.h>
+#include <api/wnd/basewnd.h>
+#include <tataki/region/api_region.h>
+
+
+
+/* various functions that might help out
+
+for drawSysObject:
+HIThemeDrawButton
+HIThemeDrawTitleBarWidget for minimize, maximize, exit
+*/
+
+inline float QuartzBlue(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[0] / 255.f;
+}
+
+inline float QuartzGreen(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[1] / 255.f;
+
+}
+
+inline float QuartzRed(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[2] / 255.f;
+
+}
+
+inline float QuartzAlpha(RGB32 color)
+{
+ unsigned char *pixel = (unsigned char *)&color;
+ return pixel[3] / 255.f;
+
+}
+
+Canvas::Canvas(CGrafPtr _context)
+{
+
+}
+
+void Canvas::fillRect(const RECT *r, ARGB32 color)
+{
+ CGContextSetRGBFillColor(context,
+ QuartzRed(color), // red
+ QuartzGreen(color), // green
+ QuartzBlue(color), // blue
+ QuartzAlpha(color) // alpha
+ );
+
+ HIRect rect = HIRectFromRECT(r);
+ CGContextFillRect(context, rect);
+}
+
+void Canvas::fillRgn(api_region *r, ARGB32 color)
+{
+ CGContextSetRGBFillColor(context,
+ QuartzRed(color), // red
+ QuartzGreen(color), // green
+ QuartzBlue(color), // blue
+ QuartzAlpha(color) // alpha
+ );
+
+ HIShapeRef shape = r->getOSHandle();
+ HIShapeReplacePathInCGContext(shape, context);
+ CGContextFillPath(context);
+}
+
+void Canvas::blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth)
+{
+ // clip dest
+ // Create CGImage from context
+ // CGContextDrawImage
+}
+
+HDC Canvas::getHDC()
+{
+ return context;
+}
+
+void Canvas::selectClipRgn(api_region *r)
+{
+ if (r)
+ {
+ HIShapeRef shape = r->getOSHandle();
+ HIShapeReplacePathInCGContext(shape, context);
+ CGContextClip(context);
+ }
+ else
+ {
+ CGContextClipToRect(context, CGRectInfinite);
+ }
+}
+
+void Canvas::stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth)
+{
+ // Create CGImage from context
+ // CGContextDrawImage
+}
+
+void Canvas::textOut(int x, int y, const wchar_t *txt, const Wasabi::FontInfo *fontInfo)
+{
+ // TODO: turn this code into a svc_fontI, and use api_font here instead
+ size_t len = wcslen(txt);
+ UniChar *unistr = (UniChar *)malloc((len + 1) * sizeof(UniChar));
+ UniChar *copy = unistr;
+ while (*txt)
+ *copy++=*txt++;
+ *copy=0;
+
+ ATSUStyle style;
+ ATSUCreateStyle(&style);
+
+ CGContextSaveGState(context);
+ CGContextSetRGBFillColor(context,
+ QuartzRed(fontInfo->color), // red
+ QuartzGreen(fontInfo->color), // green
+ QuartzBlue(fontInfo->color), // blue
+ QuartzAlpha(fontInfo->color) // alpha
+ );
+
+ ATSUTextLayout layout;
+ ATSUCreateTextLayout(&layout);
+
+ ATSUSetTextPointerLocation(layout, unistr, kATSUFromTextBeginning, kATSUToTextEnd, len);
+
+ ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
+
+ Rect imageRect;
+ ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, 0, &imageRect);
+ y-=(imageRect.bottom - imageRect.top);
+ CGContextScaleCTM(context, 1.0, -1.0);
+
+ ATSUAttributeTag tags[] = {kATSUCGContextTag};
+ ATSUAttributeValuePtr values[] = {&context};
+ ByteCount sizes[] = {sizeof(CGContextRef)};
+ ATSUSetLayoutControls(layout, 1, tags, sizes, values);
+ ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, FloatToFixed(x), FloatToFixed(y));
+ ATSUDisposeTextLayout(layout);
+ ATSUDisposeStyle(style);
+ CGContextRestoreGState(context);
+ free(unistr);
+}
+
+void Canvas::drawSysObject(const RECT *r, int sysobj, int alpha)
+{
+#warning TODO
+ using namespace DrawSysObj;
+ switch(sysobj)
+ {
+ case OSBUTTON:
+ {
+ HIRect buttonRect = HIRectFromRECT(r);
+ HIThemeButtonDrawInfo buttonDrawInfo;
+ buttonDrawInfo.version=0;
+ buttonDrawInfo.state = kThemeStateActive;
+ buttonDrawInfo.kind = kThemePushButton;
+ buttonDrawInfo.value = kThemeButtonOn;
+ buttonDrawInfo.adornment = kThemeAdornmentNone;
+ buttonDrawInfo.animation.time.start = 0;
+ buttonDrawInfo.animation.time.current=0;
+ HIThemeDrawButton(&buttonRect, &buttonDrawInfo, context, /*kHIThemeOrientationNormal*/kHIThemeOrientationInverted, 0);
+ }
+ break;
+ case OSBUTTON_PUSHED:
+ {
+ HIRect buttonRect = HIRectFromRECT(r);
+ HIThemeButtonDrawInfo buttonDrawInfo;
+ buttonDrawInfo.version=0;
+ buttonDrawInfo.state = kThemeStatePressed;
+ buttonDrawInfo.kind = kThemePushButton;
+ buttonDrawInfo.value = kThemeButtonOn;
+ buttonDrawInfo.adornment = kThemeAdornmentNone;
+ buttonDrawInfo.animation.time.start = 0;
+ buttonDrawInfo.animation.time.current=0;
+ HIThemeDrawButton(&buttonRect, &buttonDrawInfo, context, /*kHIThemeOrientationNormal*/kHIThemeOrientationInverted, 0);
+ }
+ break;
+ case OSBUTTON_DISABLED:
+ {
+ HIRect buttonRect = HIRectFromRECT(r);
+ HIThemeButtonDrawInfo buttonDrawInfo;
+ buttonDrawInfo.version=0;
+ buttonDrawInfo.state = kThemeStateInactive;
+ buttonDrawInfo.kind = kThemePushButton;
+ buttonDrawInfo.value = kThemeButtonOn;
+ buttonDrawInfo.adornment = kThemeAdornmentNone;
+ buttonDrawInfo.animation.time.start = 0;
+ buttonDrawInfo.animation.time.current=0;
+ HIThemeDrawButton(&buttonRect, &buttonDrawInfo, context, /*kHIThemeOrientationNormal*/kHIThemeOrientationInverted, 0);
+ }
+ break;
+ }
+}
+
+void Canvas::getTextExtent(const wchar_t *text, int *w, int *h, const Wasabi::FontInfo *fontInfo)
+{
+ // TODO: turn this code into a svc_fontI, and use api_font here instead
+ size_t len = wcslen(text);
+ UniChar *unistr = (UniChar *)malloc((len + 1) * sizeof(UniChar));
+ UniChar *copy = unistr;
+ while (*text)
+ *copy++=*text++;
+ *copy=0;
+
+ ATSUStyle style;
+ ATSUCreateStyle(&style);
+
+ ATSUTextLayout layout;
+ ATSUCreateTextLayout(&layout);
+
+ ATSUSetTextPointerLocation(layout, unistr, kATSUFromTextBeginning, kATSUToTextEnd, len);
+
+ ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
+
+ Rect imageRect;
+ ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, 0, &imageRect);
+ *h=(imageRect.bottom - imageRect.top);
+ *w = (imageRect.right - imageRect.left);
+
+ ATSUDisposeTextLayout(layout);
+ ATSUDisposeStyle(style);
+ free(unistr);
+}
+
+void Canvas::textOutCentered(RECT *r, const wchar_t *txt, const Wasabi::FontInfo *fontInfo)
+{
+ textOut(r->left, r->top, txt, fontInfo);
+}
+
+
+#define CBCLASS Canvas
+START_DISPATCH;
+CB(GETHDC, getHDC);
+END_DISPATCH;
+#undef CBCLASS
+
+BaseCloneCanvas::BaseCloneCanvas(ifc_canvas *cloner)
+{
+ if (cloner != NULL) clone(cloner);
+}
+
+int BaseCloneCanvas::clone(ifc_canvas *cloner)
+{
+ ASSERTPR(context == NULL, "can't clone twice");
+ context = cloner->getHDC();
+ CGContextRetain(context);
+// bits = cloner->getBits();
+// cloner->getDim(&width, &height, &pitch);
+ // srcwnd = cloner->getBaseWnd();
+// cloner->getOffsets(&xoffset, &yoffset);
+// setTextFont(cloner->getTextFont());
+// setTextSize(cloner->getTextSize());
+// setTextBold(cloner->getTextBold());
+// setTextOpaque(cloner->getTextOpaque());
+// setTextUnderline(cloner->getTextUnderline());
+// setTextItalic(cloner->getTextItalic());
+// setTextAlign(cloner->getTextAlign());
+// setTextColor(cloner->getTextColor());
+// setTextBkColor(cloner->getTextBkColor());
+ return (context != NULL);
+}
+
+BaseCloneCanvas::~BaseCloneCanvas()
+{
+ CGContextRelease(context);
+ context = NULL;
+}
+
diff --git a/Src/Wasabi/api/wnd/platform/osx/osx_region_hishape.cpp b/Src/Wasabi/api/wnd/platform/osx/osx_region_hishape.cpp
new file mode 100644
index 00000000..348ba1de
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/osx_region_hishape.cpp
@@ -0,0 +1,217 @@
+#include <Carbon/Carbon.h>
+#include <tataki/region/region.h>
+#include <tataki/bitmap/bitmap.h>
+
+RegionI::RegionI() : rgn(0)
+{
+}
+
+RegionI::RegionI(const RECT *r) : rgn(0)
+{
+ setRect(r);
+}
+
+RegionI::RegionI(HIMutableShapeRef _rgn) : rgn(_rgn)
+{
+}
+
+RegionI::RegionI(HIShapeRef _rgn)
+{
+ rgn=HIShapeCreateMutableCopy(_rgn);
+}
+
+RegionI::~RegionI()
+{
+ if (rgn)
+ CFRelease(rgn);
+}
+
+RegionI::RegionI(RgnHandle qdrgn)
+{
+ HIShapeRef shape = HIShapeCreateWithQDRgn(qdrgn);
+ rgn = HIShapeCreateMutableCopy(shape);
+ CFRelease(shape);
+}
+
+RegionI::RegionI(SkinBitmap *bitmap)
+{
+ // TODO: we need to find a much better way to do this
+ RECT r;
+ r.left=0;
+ r.top=0;
+ r.right=bitmap->getWidth();
+ r.bottom=bitmap->getHeight();
+ setRect(&r);
+}
+
+
+OSREGIONHANDLE RegionI::getOSHandle()
+{
+ if (!rgn)
+ rgn = HIShapeCreateMutable();
+ return rgn;
+}
+
+api_region *RegionI::clone()
+{
+ if (!rgn)
+ return new RegionI();
+ else
+ return new RegionI(HIShapeCreateMutableCopy(rgn));
+}
+
+void RegionI::disposeClone(api_region *r)
+{
+ if (r) // yes we need to check for NULL here because r != static_cast<>(r)
+ delete static_cast<RegionI *>(r);
+}
+
+bool RegionI::ptInRegion(const POINT *pt)
+{
+ if (!rgn)
+ return false;
+ HIPoint hipt = HIPointFromPOINT(pt);
+ return !!HIShapeContainsPoint(rgn, &hipt);
+}
+
+void RegionI::offset(int x, int y)
+{
+ if (!rgn)
+ rgn = HIShapeCreateMutable();
+
+ HIShapeOffset(rgn, x, y);
+}
+
+void RegionI::getBox(RECT *r)
+{
+ if (!rgn) // TODO: we could manually set r to 0,0,0,0
+ rgn = HIShapeCreateMutable();
+
+ HIRect rect;
+ HIShapeGetBounds(rgn, &rect);
+ *r = RECTFromHIRect(&rect);
+}
+
+void RegionI::subtractRegion(const api_region *r)
+{
+ if (rgn)
+ {
+ api_region *reg = const_cast<api_region *>(r);
+ HIShapeRef sub = reg->getOSHandle();
+ HIShapeDifference(rgn,sub, rgn);
+ }
+}
+
+void RegionI::subtractRect(const RECT *r)
+{
+ if (rgn)
+ {
+ HIRect rect = HIRectFromRECT(r);
+ HIShapeRef sub = HIShapeCreateWithRect(&rect);
+ HIShapeDifference(rgn, sub, rgn);
+ }
+}
+
+void RegionI::addRect(const RECT *r)
+{
+ if (!rgn)
+ rgn = HIShapeCreateMutable();
+ HIRect rect = HIRectFromRECT(r);
+ HIShapeRef add = HIShapeCreateWithRect(&rect);
+ HIShapeUnion(rgn, add, rgn);
+}
+
+void RegionI::addRegion(const api_region *r)
+{
+ if (!rgn)
+ rgn = HIShapeCreateMutable();
+ api_region *reg = const_cast<api_region *>(r);
+ HIShapeRef add = reg->getOSHandle();
+ HIShapeUnion(rgn, add, rgn);
+}
+
+void RegionI::andRegion(const api_region *r)
+{
+ if (rgn) // intersection with empty region will always be empty
+ {
+ api_region *reg = const_cast<api_region *>(r);
+ HIShapeRef intersection = reg->getOSHandle();
+ HIShapeIntersect(rgn, intersection, rgn);
+ }
+}
+
+void RegionI::setRect(const RECT *r)
+{
+ if (rgn)
+ CFRelease(rgn);
+ HIRect rect = HIRectFromRECT(r);
+ HIShapeRef rectRgn = HIShapeCreateWithRect(&rect);
+ rgn = HIShapeCreateMutableCopy(rectRgn);
+ CFRelease(rectRgn);
+}
+
+void RegionI::empty()
+{
+ if (rgn)
+ CFRelease(rgn);
+ rgn=0;
+}
+
+int RegionI::isEmpty()
+{
+ if (!rgn)
+ return 1;
+ return !!HIShapeIsEmpty(rgn);
+}
+
+int RegionI::isRect()
+{
+ if (!rgn)
+ return 1;
+ return !!HIShapeIsRectangular(rgn);
+}
+
+int RegionI::intersectRgn(const api_region *r, api_region *intersection)
+{
+ intersection->empty();
+ intersection->addRegion(this);
+ intersection->andRegion(r);
+ return !intersection->isEmpty();
+}
+
+int RegionI::intersectRect(const RECT *r, api_region *intersection)
+{
+ intersection->setRect(r);
+ intersection->andRegion(this);
+ return !intersection->isEmpty();
+}
+
+#define CBCLASS RegionI
+START_DISPATCH;
+CB(REGION_GETOSHANDLE, getOSHandle);
+CB(REGION_CLONE, clone);
+VCB(REGION_DISPOSECLONE, disposeClone);
+CB(REGION_PTINREGION, ptInRegion);
+VCB(REGION_OFFSET, offset);
+VCB(REGION_GETBOX, getBox);
+VCB(REGION_SUBTRACTRGN, subtractRegion);
+VCB(REGION_SUBTRACTRECT, subtractRect);
+VCB(REGION_ADDRECT, addRect);
+VCB(REGION_ADD, addRegion);
+VCB(REGION_AND, andRegion);
+VCB(REGION_SETRECT, setRect);
+VCB(REGION_EMPTY, empty);
+CB(REGION_ISEMPTY, isEmpty);
+CB(REGION_ISRECT, isRect);
+CB(REGION_INTERSECTRGN, intersectRgn);
+CB(REGION_INTERSECTRECT, intersectRect);
+END_DISPATCH;
+#undef CBCLASS
+
+#define CBCLASS RegionServerI
+START_DISPATCH;
+VCB(REGIONSERVER_ADDREF, addRef);
+VCB(REGIONSERVER_DELREF, delRef);
+CB(REGIONSERVER_GETREGION, getRegion);
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Wasabi/api/wnd/platform/osx/region.h b/Src/Wasabi/api/wnd/platform/osx/region.h
new file mode 100644
index 00000000..9879b642
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/osx/region.h
@@ -0,0 +1,115 @@
+#ifndef __REGION_H
+#define __REGION_H
+
+#include <Carbon/Carbon.h>
+#include <bfc/platform/platform.h>
+#include <tataki/region/api_region.h>
+
+class SkinBitmap;
+
+class RegionI : public api_region
+{
+public:
+ RegionI();
+ RegionI(const RECT *r);
+ RegionI(RgnHandle qdrgn);
+ RegionI(HIShapeRef _rgn);
+ RegionI(SkinBitmap *bitmap);
+ ~RegionI();
+
+ // api_region
+ OSREGIONHANDLE getOSHandle();
+ api_region *clone();
+ void disposeClone(api_region *r);
+ bool ptInRegion(const POINT *pt);
+ void offset(int x, int y);
+ void getBox(RECT *r);
+ void subtractRegion(const api_region *r);
+ void subtractRect(const RECT *r);
+ void addRect(const RECT *r);
+ void addRegion(const api_region *r);
+ void andRegion(const api_region *r);
+ void setRect(const RECT *r);
+ void empty();
+ int isEmpty();
+ int equals(const api_region *r);
+ int enclosed(const api_region *r, api_region *outside = NULL);
+ int intersectRgn(const api_region *r, api_region *intersection);
+ int doesIntersectRgn(const api_region *r);
+ int intersectRect(const RECT *r, api_region *intersection);
+
+ int isRect();
+ void scale(double sx, double sy, bool round = 0);
+ void debug(int async = 0);
+ OSREGIONHANDLE makeWindowRegion(); // gives you a handle to a clone of the OSREGION object so you can insert it into a window's region with SetWindowRgn. ANY other use is prohibited
+
+ // this is how you can enumerate the subrects that compose to make up the
+ // entire region
+ int getNumRects();
+ int enumRect(int n, RECT *r);
+
+
+private:
+ RegionI(HIMutableShapeRef _rgn);
+ HIMutableShapeRef rgn;
+
+protected:
+ RECVS_DISPATCH;
+};
+
+
+// TODO: we could take of advantage of HIShapeRef's built in reference counting to implement this
+class RegionServer : public Dispatchable {
+
+protected:
+ RegionServer() {}
+ virtual ~RegionServer() {}
+
+public:
+
+ void addRef(void *client);
+ void delRef(void *client);
+ api_region *getRegion();
+
+ enum {
+ REGIONSERVER_ADDREF = 500,
+ REGIONSERVER_DELREF = 550,
+ REGIONSERVER_GETREGION = 600,
+ };
+};
+
+inline void RegionServer::addRef(void *client) {
+ _voidcall(REGIONSERVER_ADDREF, (api_region *)NULL, client);
+}
+
+inline void RegionServer::delRef(void *client) {
+ _voidcall(REGIONSERVER_DELREF, client);
+}
+
+inline api_region * RegionServer::getRegion() {
+ return _call(REGIONSERVER_GETREGION, (api_region *)NULL);
+}
+
+class RegionServerI : public RegionServer {
+public :
+
+ RegionServerI() { numrefs = 0; }
+ virtual ~RegionServerI() {}
+
+ virtual void addRef(void *client) { numrefs++; }
+ virtual void delRef(void *client) { numrefs--; }
+ virtual api_region *getRegion()=0;
+
+ virtual int getNumRefs() { return numrefs; }
+
+protected:
+
+ RECVS_DISPATCH;
+
+private:
+
+ int numrefs;
+};
+#endif
+
+
diff --git a/Src/Wasabi/api/wnd/platform/win32/bitmap.h b/Src/Wasabi/api/wnd/platform/win32/bitmap.h
new file mode 100644
index 00000000..589f9a13
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/win32/bitmap.h
@@ -0,0 +1,81 @@
+//NONPORTABLE
+#ifndef _BITMAP_H
+#define _BITMAP_H
+
+//#include <wasabicfg.h>
+//#include <bfc/common.h>
+#include <bfc/string/string.h>
+#include <bfc/string/StringW.h>
+
+class ifc_canvas; // see canvas.h
+
+//#define NO_MMX
+
+class api_region;
+
+// a skinnable bitmap
+class SkinBitmap
+{
+public:
+#ifndef _NOSTUDIO
+#ifdef WASABI_COMPILE_IMGLDR
+#ifdef _WIN32
+ SkinBitmap(HINSTANCE hInst, int _id, const wchar_t *colorgroup = NULL); //NONPORTABLE
+#endif
+ SkinBitmap(const wchar_t *elementname, int cached = 1);
+#endif
+#endif
+ // SkinBitmap(SkinBitmap *source, int w, int h);
+ SkinBitmap(int w, int h, ARGB32 bgcolor = RGBA(255,255,255,255)); //untested --BU
+#ifdef _WIN32
+ SkinBitmap(HBITMAP bitmap);
+ SkinBitmap(HBITMAP bitmap, HDC dc, int has_alpha = 0, void *bits = NULL);
+#endif
+ SkinBitmap(ARGB32 *bits, int w, int h); // added by benski, use if you have raw image bits
+ ~SkinBitmap();
+
+int getWidth() const { return subimage_w == -1 ? fullimage_w : subimage_w; };
+int getHeight() const { return subimage_h == -1 ? fullimage_h : subimage_h; };
+ int getFullWidth() const { return fullimage_w; };
+ int getFullHeight() const { return fullimage_h; };
+int getX() const { return x_offset == -1 ? 0 : x_offset; };
+int getY() const { return y_offset == -1 ? 0 : y_offset; };
+ int getBpp() const { return 32; };
+ int getAlpha() const { return has_alpha; };
+ void setHasAlpha(int ha);
+ virtual void *getBits();
+ int isInvalid();
+
+ const wchar_t *getBitmapName();
+
+ void blit(ifc_canvas *canvas, int x, int y);
+ void blitAlpha(ifc_canvas *canvas, int x, int y, int alpha = 255);
+ // blits a chunk of source into dest rect
+ void blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha = 255);
+ void blitTile(ifc_canvas *canvas, RECT *dest, int xoffs = 0, int yoffs = 0, int alpha = 255);
+ void blitRectToTile(ifc_canvas *canvas, RECT *dest, RECT *src, int xoffs = 0, int yoffs = 0, int alpha = 255);
+ void stretch(ifc_canvas *canvas, int x, int y, int w, int h);
+ void stretchToRect(ifc_canvas *canvas, RECT *r);
+ void stretchRectToRect(ifc_canvas *canvas, RECT *src, RECT *dst);
+
+ void stretchToRectAlpha(ifc_canvas *canvas, RECT *r, int alpha = 255);
+ void stretchToRectAlpha(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha = 255);
+ ARGB32 getPixel(int x, int y);
+
+private:
+#ifdef _WIN32
+ void bmpToBits(HBITMAP hbmp, HDC defaultDC = NULL);
+#endif
+
+ int has_alpha;
+
+ int x_offset, y_offset, subimage_w, subimage_h, fullimage_w, fullimage_h;
+
+ ARGB32 *bits;
+ int ownbits;
+ int last_failed;
+ StringW bitmapname;
+ int fromskin;
+};
+
+#endif
diff --git a/Src/Wasabi/api/wnd/platform/win32/canvas.h b/Src/Wasabi/api/wnd/platform/win32/canvas.h
new file mode 100644
index 00000000..e6dea753
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/win32/canvas.h
@@ -0,0 +1 @@
+#include <tataki/canvas/win/canvas.h>
diff --git a/Src/Wasabi/api/wnd/platform/win32/region.h b/Src/Wasabi/api/wnd/platform/win32/region.h
new file mode 100644
index 00000000..88491634
--- /dev/null
+++ b/Src/Wasabi/api/wnd/platform/win32/region.h
@@ -0,0 +1,135 @@
+#ifndef __REGION_H
+#define __REGION_H
+
+#include <api/wnd/bitmap.h>
+#include <bfc/dispatch.h>
+
+class BaseWnd;
+class Canvas;
+class api_region;
+class RegionServer;
+
+#include "api_region.h"
+
+class RegionI : public api_region
+{
+public:
+ RegionI();
+ RegionI(const RegionI *copy);
+ RegionI(const RECT *r);
+ RegionI(int l, int t, int r, int b);
+ RegionI(OSREGIONHANDLE region);
+ RegionI(SkinBitmap *bitmap, RECT *r=NULL, int xoffset=0, int yoffset=0, bool inverted=false, int dothreshold=0, __int8 threshold=0, int threversed=0, int minalpha=1);
+ RegionI(Canvas *c, RECT *defboundbox=NULL);
+ virtual ~RegionI();
+
+ api_region *clone();
+ void disposeClone(api_region *r);
+ bool ptInRegion(const POINT *pt);
+ void offset(int x, int y);
+ void getBox(RECT *r);
+ void subtractRegion(const api_region *reg);
+ void subtractRect(const RECT *r);
+ void addRect(const RECT *r);
+ void addRegion(const api_region *r);
+ void andRegion(const api_region *r);
+ void setRect(const RECT *r);
+ void empty();
+ int isEmpty();
+ int equals(const api_region *r);
+ int enclosed(const api_region *r, api_region *outside=NULL);
+ int intersectRgn(const api_region *r, api_region *intersection);
+ int doesIntersectRgn(const api_region *r);
+ int intersectRect(const RECT *r, api_region *intersection);
+ int doesIntersectRect(const RECT *r);
+ int isRect();
+ void scale(double sx, double sy, bool round=0);
+ void debug(int async=0);
+
+ // NONPORTABLE
+
+ OSREGIONHANDLE makeWindowRegion(); // gives you a handle to a clone of the OSREGION object so you can insert it into a window's region with SetWindowRgn. ANY other use is prohibited
+ OSREGIONHANDLE getOSHandle(); // avoid as much as you can, should be used only by WIN32-dependant classes
+
+ // END NONPORTABLE
+
+ int getNumRects();
+ int enumRect(int n, RECT *r);
+
+ OSREGIONHANDLE alphaToRegionRect(void *pbits32, int bmX, int bmY, int bmWidth, int bmHeight, int fullw, int fullh, int xoffset, int yoffset, bool portion, int _x, int _y, int _w, int _h, bool inverted, int dothreshold, unsigned __int8 threshold, int thinverse, int minalpha);
+
+private:
+
+ inline void init();
+ void optimize();
+ void deoptimize();
+
+ OSREGIONHANDLE hrgn;
+ OSREGIONHANDLE alphaToRegionRect(SkinBitmap *bitmap, int xoffset, int yoffset, bool portion, int _x, int _y, int _w, int _h, bool inverted=false, int dothreshold=0, unsigned __int8 threshold=0, int thinverse=0, int minalpha=1/* 1..255*/);
+ RECT overlay;
+ int clonecount;
+ RegionI *lastdebug;
+ RegionServer *srv;
+ RECT optrect;
+ int optimized;
+
+protected:
+
+ RECVS_DISPATCH;
+};
+
+class RegionServer : public Dispatchable {
+
+ protected:
+ RegionServer() {}
+ virtual ~RegionServer() {}
+
+ public:
+
+ void addRef(void *client);
+ void delRef(void *client);
+ api_region *getRegion();
+
+ enum {
+ REGIONSERVER_ADDREF = 500,
+ REGIONSERVER_DELREF = 550,
+ REGIONSERVER_GETREGION = 600,
+ };
+};
+
+inline void RegionServer::addRef(void *client) {
+ _voidcall(REGIONSERVER_ADDREF, (api_region *)NULL, client);
+}
+
+inline void RegionServer::delRef(void *client) {
+ _voidcall(REGIONSERVER_DELREF, client);
+}
+
+inline api_region * RegionServer::getRegion() {
+ return _call(REGIONSERVER_GETREGION, (api_region *)NULL);
+}
+
+class RegionServerI : public RegionServer {
+ public :
+
+ RegionServerI() { numrefs = 0; }
+ virtual ~RegionServerI() {}
+
+ virtual void addRef(void *client) { numrefs++; }
+ virtual void delRef(void *client) { numrefs--; }
+ virtual api_region *getRegion()=0;
+
+ virtual int getNumRefs() { return numrefs; }
+
+ protected:
+
+ RECVS_DISPATCH;
+
+ private:
+
+ int numrefs;
+};
+
+#endif
+
+