diff options
Diffstat (limited to 'Src/tataki')
46 files changed, 9148 insertions, 0 deletions
diff --git a/Src/tataki/api__tataki.h b/Src/tataki/api__tataki.h new file mode 100644 index 00000000..89098039 --- /dev/null +++ b/Src/tataki/api__tataki.h @@ -0,0 +1,41 @@ +#ifndef NULLSOFT_TATAKI_API_H +#define NULLSOFT_TATAKI_API_H + +#include <api/service/api_service.h> +//extern api_service *serviceManager; +//#define WASABI_API_SVC serviceManager + +#include <api/application/api_application.h> +#define WASABI_API_APP applicationApi + +#include <api/syscb/api_syscb.h> +#define WASABI_API_SYSCB sysCallbackApi + +#include <api/font/api_font.h> +#define WASABI_API_FONT fontApi + +#include <api/wnd/api_wnd.h> +#define WASABI_API_WND wndApi + +#include <api/config/api_config.h> +#define WASABI_API_CONFIG configApi + +#include <api/imgldr/api_imgldr.h> +#define WASABI_API_IMGLDR imgLoaderApi + +#include <Agave/Random/api_random.h> +extern api_random *randomApi; +#define AGAVE_API_RANDOM randomApi + +#include <api/memmgr/api_memmgr.h> +extern api_memmgr *memoryManager; +#define WASABI_API_MEMMGR memoryManager + +#include <api/skin/api_skin.h> +#define WASABI_API_SKIN skinApi + +#include <api/skin/api_palette.h> +extern api_palette *paletteManagerApi; +#define WASABI_API_PALETTE paletteManagerApi + +#endif
\ No newline at end of file diff --git a/Src/tataki/bitmap/autobitmap.cpp b/Src/tataki/bitmap/autobitmap.cpp new file mode 100644 index 00000000..9c85c586 --- /dev/null +++ b/Src/tataki/bitmap/autobitmap.cpp @@ -0,0 +1,201 @@ +#include <tataki/api__tataki.h> +#include "autobitmap.h" +#include <bfc/assert.h> +#define TIMER_ID_RESET 0x1664 + +#ifdef DROP_BITMAP_ON_IDLE +// these are in seconds +#define DROP_MINDELAY 3 +#define DROP_MAXDELAY 15 +#define DROP_INITIALBUMP -5 +#define DROP_MINDELAYSINCELASTUSE 7 +#endif + +/* +#ifdef _WIN32 +extern HINSTANCE hInstance; +#endif +*/ + +AutoSkinBitmap::AutoSkinBitmap(const wchar_t *_name) +{ + bitmap = NULL; + use = 0; + id = 0; + colorgroup = 0; + name = 0; + resamplingMode = RESAMPLING_MODE_NONE; +#ifdef WIN32 + myInstance = 0; +#endif +#ifdef DROP_BITMAP_ON_IDLE + lastuse = 0; +#endif + setBitmap(_name); +} + +AutoSkinBitmap::~AutoSkinBitmap() +{ +#ifdef DROP_BITMAP_ON_IDLE + timerclient_killTimer(TIMER_ID_RESET); +#endif + if (bitmap) bitmap->Release(); + ASSERT(WASABI_API_SYSCB != NULL); + WASABI_API_SYSCB->syscb_deregisterCallback(this); + free(colorgroup); + free(name); +} + +const wchar_t *AutoSkinBitmap::setBitmap(const wchar_t *_name) +{ + if (_name == NULL) return NULL; + if (name == NULL || wcscmp(name, _name)) + { + reset(); + free(name); + name = _wcsdup(_name); + } + return name; +} + +int AutoSkinBitmap::setBitmap(int _id) +{ + if (_id == 0) return 0; + if (_id != id) + { + reset(); + id = _id; + } + return id; +} + +#ifdef _WIN32 +void AutoSkinBitmap::setHInstance(HINSTANCE hinstance) +{ + myInstance = hinstance; +} +#endif + +void AutoSkinBitmap::reset() +{ + if (bitmap) bitmap->Release(); bitmap = NULL; +#ifdef DROP_BITMAP_ON_IDLE + timerclient_killTimer(TIMER_ID_RESET); +#endif +} +static int modrandom(int max) +{ + int ret = AGAVE_API_RANDOM->GetPositiveNumber(); + ret %= max; + return ret; +} +SkinBitmap *AutoSkinBitmap::getBitmap() +{ + //FG ASSERT(name != NULL); + if ((name == NULL || (name != NULL && *name == NULL)) && id == NULL) return NULL; + if (bitmap == NULL) + { + if (name) + { + switch (resamplingMode) + { + case RESAMPLING_MODE_SUPERSAMPLING: + bitmap = new HQSkinBitmap(name); + break; + case RESAMPLING_MODE_NONE: + default: + bitmap = new SkinBitmap(name); + break; + } + } + else + { +#ifdef WIN32 + switch (resamplingMode) + { + case RESAMPLING_MODE_SUPERSAMPLING: + bitmap = new HQSkinBitmap(myInstance, id, colorgroup); + break; + case RESAMPLING_MODE_NONE: + default: + bitmap = new SkinBitmap(myInstance, id, colorgroup); + break; + } +#endif + } + ASSERT(WASABI_API_SYSCB != NULL); + if (bitmap) + WASABI_API_SYSCB->syscb_registerCallback(this); +#ifdef DROP_BITMAP_ON_IDLE + if (bitmap) + { + lastuse = GetTickCount() + DROP_INITIALBUMP; + timerclient_setTimer(TIMER_ID_RESET, DROP_MINDELAY*1000 + modrandom((DROP_MAXDELAY - DROP_MINDELAY)*1000)); + return bitmap; + } +#endif + + } +#ifdef DROP_BITMAP_ON_IDLE + if (bitmap) lastuse = GetTickCount(); +#endif + return bitmap; +} + +const wchar_t *AutoSkinBitmap::getBitmapName() +{ + return name; +} + +int AutoSkinBitmap::skincb_onReset() +{ + reset(); + return 1; +} + +void AutoSkinBitmap::setHInstanceBitmapColorGroup(const wchar_t *_colorgroup) +{ + free(colorgroup); + if (_colorgroup) + colorgroup = _wcsdup(_colorgroup); + else + colorgroup=0; +} + +#ifdef DROP_BITMAP_ON_IDLE +void AutoSkinBitmap::timerclient_timerCallback(int id) +{ + if (id == TIMER_ID_RESET) + { + tryUnload(); + } + else TimerClientDI::timerclient_timerCallback(id); +} + +void AutoSkinBitmap::tryUnload() +{ + DWORD now = GetTickCount(); + if (now < lastuse + DROP_MINDELAYSINCELASTUSE*1000) return ; + reset(); +} +#endif + +void AutoSkinBitmap::setResamplingMode(int mode) +{ + this->resamplingMode = mode; + this->reset(); +} + +int AutoSkinBitmap::getResamplingMode() +{ + return this->resamplingMode; +} + + +#define CBCLASS AutoSkinBitmap +START_DISPATCH; + CB(SYSCALLBACK_GETEVENTTYPE, getEventType); + CB(SYSCALLBACK_NOTIFY, notify); +END_DISPATCH; +#undef CBCLASS + diff --git a/Src/tataki/bitmap/autobitmap.h b/Src/tataki/bitmap/autobitmap.h new file mode 100644 index 00000000..c1303b3c --- /dev/null +++ b/Src/tataki/bitmap/autobitmap.h @@ -0,0 +1,106 @@ +#ifndef _AUTOBITMAP_H +#define _AUTOBITMAP_H + +#include "bitmap.h" +#include <api/syscb/callbacks/syscb.h> +#include <api/syscb/callbacks/skincb.h> +#include <tataki/export.h> + +#ifdef DROP_BITMAP_ON_IDLE +#include <api/timer/timerclient.h> +#define DROP_BITMAP_ANCESTOR , public TimerClientDI +#else +#define DROP_BITMAP_ANCESTOR +#endif + + +class TATAKIAPI AutoSkinBitmap : public SysCallback DROP_BITMAP_ANCESTOR { +public: + AutoSkinBitmap(const wchar_t *_name=NULL); + virtual ~AutoSkinBitmap(); + + const wchar_t *setBitmap(const wchar_t *_name=NULL); + int setBitmap(int _id=0); + + // call this when you get freeResources called on you + // doesn't hurt to call as much as you want + void reset(); + void reload() { getBitmap(); } // force a reload + + // this loads the bitmap if necessary + SkinBitmap *getBitmap(); + operator SkinBitmap *() { return getBitmap(); } + + const wchar_t *operator =(const wchar_t *_name) { return setBitmap(_name); } + int operator =(int _id) { return setBitmap(_id); } + + const wchar_t *getBitmapName(); + + void setHInstanceBitmapColorGroup(const wchar_t *_colorgroup); + + enum + { + RESAMPLING_MODE_NONE = 0, + RESAMPLING_MODE_SUPERSAMPLING = 1, + }; + + void setResamplingMode(int mode); + int getResamplingMode(); + + // feel free to add more methods here to help make using this class + // transparent... + int getWidth() { return getBitmap()->getWidth(); }; + int getHeight() { return getBitmap()->getHeight(); }; + void stretchToRectAlpha(ifc_canvas *canvas, RECT *r, int alpha=255) { + getBitmap()->stretchToRectAlpha(canvas, r, alpha); + } + void stretchToRectAlpha(ifc_canvas *canvas, RECT *r, RECT *dest, int alpha=255) { + getBitmap()->stretchToRectAlpha(canvas, r, dest, alpha); + } + void stretchToRect(ifc_canvas *canvas, RECT *r) { + getBitmap()->stretchToRect(canvas, r); + } + void blitAlpha(ifc_canvas *canvas, int x, int y, int alpha=255) { + getBitmap()->blitAlpha(canvas, x, y, alpha); + } + +#ifdef _WIN32 + void setHInstance(HINSTANCE hinstance); // use this if you use autoskinbitmap and resource in a wac +#endif +#ifdef DROP_BITMAP_ON_IDLE + virtual void timerclient_timerCallback(int id); +#endif + +protected: + FOURCC getEventType() { return SysCallback::SKINCB; } + int notify(int msg, intptr_t param1 = 0, intptr_t param2 = 0) + { + if (msg == SkinCallback::RESET) + return skincb_onReset(); + else + return 0; + } + + int skincb_onReset(); +#ifdef DROP_BITMAP_ON_IDLE + virtual void tryUnload(); +#endif + +private: + int use; + int id; + wchar_t *name; + wchar_t *colorgroup; + SkinBitmap *bitmap; + int resamplingMode; +#ifdef _WIN32 + HINSTANCE myInstance; +#endif +#ifdef DROP_BITMAP_ON_IDLE + uint32_t lastuse; +#endif +protected: + RECVS_DISPATCH; +}; + +#endif diff --git a/Src/tataki/bitmap/bitmap.h b/Src/tataki/bitmap/bitmap.h new file mode 100644 index 00000000..3eced689 --- /dev/null +++ b/Src/tataki/bitmap/bitmap.h @@ -0,0 +1,7 @@ +#ifdef _WIN32 +#include "win/bitmap.h" +#elif defined(__APPLE__) +#include "mac/osx_bitmap_cgimage.h" +#else +#error port me +#endif
\ No newline at end of file diff --git a/Src/tataki/bitmap/ifc_bitmap.h b/Src/tataki/bitmap/ifc_bitmap.h new file mode 100644 index 00000000..560d13a4 --- /dev/null +++ b/Src/tataki/bitmap/ifc_bitmap.h @@ -0,0 +1,51 @@ +#ifndef NULLSOFT_WASABI_IFC_BITMAP_H +#define NULLSOFT_WASABI_IFC_BITMAP_H + +#include <bfc/dispatch.h> +#include <bfc/platform/types.h> +#include <bfc/platform/platform.h> + +#warning move this typedef to bfc/platform/platform.h +#ifdef _WIN32 +typedef HBITMAP OSBITMAPHANDLE; +#elif defined(__APPLE__) +typedef CGImageRef OSBITMAPHANDLE; +#else +#error port me +#endif + +class ifc_bitmap : public Dispatchable +{ +protected: + ifc_bitmap() {} + ~ifc_bitmap() {} +public: + OSBITMAPHANDLE GetBitmap(); + uint8_t *GetBits(); + void UpdateBits(uint8_t *bits); // call to signify that you've modified the underlying bits. + + DISPATCH_CODES + { + IFC_BITMAP_GETBITMAP = 10, + IFC_BITMAP_GETBITS = 20, + IFC_BITMAP_UPDATEBITS = 30, + }; +}; + + +inline OSBITMAPHANDLE ifc_bitmap::GetBitmap() +{ + return _call(IFC_BITMAP_GETBITMAP, (OSBITMAPHANDLE)0); +} + +inline uint8_t *ifc_bitmap::GetBits() +{ + return _call(IFC_BITMAP_GETBITS, (uint8_t *)0); +} + +inline void ifc_bitmap::UpdateBits(uint8_t *bits) +{ + _voidcall(IFC_BITMAP_UPDATEBITS, bits); +} + +#endif
\ No newline at end of file diff --git a/Src/tataki/bitmap/mac/osx_bitmap_cgimage.cpp b/Src/tataki/bitmap/mac/osx_bitmap_cgimage.cpp new file mode 100644 index 00000000..9e1c33c2 --- /dev/null +++ b/Src/tataki/bitmap/mac/osx_bitmap_cgimage.cpp @@ -0,0 +1,219 @@ +#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; + bits = NULL; + 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); +#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(api_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(api_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(api_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(api_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(api_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/tataki/bitmap/mac/osx_bitmap_cgimage.h b/Src/tataki/bitmap/mac/osx_bitmap_cgimage.h new file mode 100644 index 00000000..0e842c08 --- /dev/null +++ b/Src/tataki/bitmap/mac/osx_bitmap_cgimage.h @@ -0,0 +1,48 @@ +#ifndef NULLSOFT_WASABI_OSX_BITMAP_CGIMAGE_H +#define NULLSOFT_WASABI_OSX_BITMAP_CGIMAGE_H + +#include <tataki/export.h> +#include <bfc/platform/platform.h> +#include <tataki/canvas/api_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 TATAKIAPI 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(api_canvas *canvas, int x, int y); + void blitAlpha(api_canvas *canvas, int x, int y, int alpha = 255); + // stretch blits + void stretchToRect(api_canvas *canvas, RECT *r); + void stretchToRectAlpha(api_canvas *canvas, RECT *r, int alpha = 255); + void stretchToRectAlpha(api_canvas *canvas, RECT *src, RECT *dst, int alpha = 255); +// tiled blits + void blitTile(api_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/tataki/bitmap/win/bitmap.cpp b/Src/tataki/bitmap/win/bitmap.cpp new file mode 100644 index 00000000..24ea0228 --- /dev/null +++ b/Src/tataki/bitmap/win/bitmap.cpp @@ -0,0 +1,1874 @@ +#include <tataki/api__tataki.h> + +//#define NO_SIMPLEFASTMODE +#include <api/imgldr/api_imgldr.h> +#include <tataki/blending/blending.h> + +#include "bitmap.h" + +#include <bfc/wasabi_std.h> +#include <tataki/canvas/bltcanvas.h> + +#include <api/memmgr/api_memmgr.h> + + +#if !defined(WIN32) && !defined(LINUX) +#error port me! +#endif + +#define ERRORBMP L"wasabi.bitmapnotfound" +#define HARDERRORBMP L"xml/wasabi/window/error.png" +// do not define NO_MMX in this file. :) + +#ifndef NO_MMX + +#ifdef WIN32 +#define MMX_CONST const +#else +#define MMX_CONST +#endif + +static unsigned int MMX_CONST SkinBitmap_mmx_revn2[2]={0x01000100,0x01000100}; +static unsigned int MMX_CONST SkinBitmap_mmx_zero[2]; +static unsigned int MMX_CONST SkinBitmap_mmx_one[2]={1,0}; +#define HAS_MMX Blenders::MMX_AVAILABLE() + +#else + +//NO_MMX defined +#define HAS_MMX 0 + +#endif +#if 0 + int bitmap_x = bitmap->getX(); + int bitmap_y = bitmap->getY(); + int bmpheight = bitmap->getHeight(); + int fullimage_w = bitmap->getFullWidth(); + void *bits = bitmap->getBits(); + int xp=xe-xs; + for (int yp = ys; yp < ye; yp ++) + { + int t=yv>>16; + if (t < 0) t=0; + if (t >= bmpheight) t=bmpheight-1; + int *psrc=((int*)bits) + (t+bitmap_y)*fullimage_w + bitmap_x; + int *dest=((int*)dib) + pitch*yp + xs; + + C::stretch(xp, psrc, dest, xstart, dxv, alpha); + + yv+=dyv; + } + } +#endif + static __inline int shc(int offset, int offset16, int pos, int delta) + { + __int64 num = (Int32x32To64(pos, delta) + (__int64)offset16)/65536LL; + return (int)(num+offset); + } + + static __inline void *ROUNDUP16(void *ptr) + { + return (void *)(((size_t)ptr+15) & ~15); + } + +static void Shrink(SkinBitmap *src_, int ys, int ye, int xe, int xs, int xstart, int yv, void *dst_, int dstpitch, int dxv, int dyv, int alpha) +{ +// to scale an image + // where the destination image is both smaller on X *and* Y. + + // inputs: + int srcpitch = src_->getFullWidth(); + int bitmap_x = src_->getX(); + int bitmap_height = src_->getHeight(); + int bitmap_fullheight = src_->getFullHeight(); + int bitmap_y = src_->getY(); + + uint8_t *src=(uint8_t *)src_->getBits();; + ARGB32 *dst= (ARGB32 *)dst_; + +//#define NEW_X(x__) ((srcxs+bitmap_x)+MulDiv(x__, dxv, 65536)) +#define NEW_X(x__) shc(bitmap_x, xstart,(x__), dxv) +#define NEW_Y(y__) shc(bitmap_y, yv, (y__)-ys, dyv) + + int dstw = xe-xs; + // make sure we have enough room. I don't think anyone is going to have destination bitmaps this big, but might as well play it safe + ASSERT(dstw <= 4096); + if (dstw > 4096) return; + + // all this weird stuff is to align on 16 byte boundary + char *_new_x[4096*sizeof(int)+15] = {0}; + char *new_x_aligned = (char *)_new_x; + ROUNDUP16(new_x_aligned); + int *new_x = (int *)new_x_aligned; + for (int x=0; x<=dstw; x++) + new_x[x] = NEW_X(x); + + // FOR EACH DEST PIXEL + for (int y=ys; y<ye; y++) + { + int sy1 = NEW_Y(y); + int sy2 = NEW_Y(y+1); + for (int x=0; x<dstw; x++) + { + uint32_t sum[4] = { 0, 0, 0, 0 }; + int sx1 = new_x[x]; + int sx2 = new_x[x+1]; + // FOR EACH CONTRIBUTING SOURCE PIXEL: in a block [sx1..sx2) x [sy1..sy2) + for (int b=sy1; b<sy2; b++) + for (int a=sx1; a<sx2; a++) + { + uint8_t *ps = &src[(b*srcpitch + a)*4]; + sum[0] += (uint32_t)ps[0]; + sum[1] += (uint32_t)ps[1]; + sum[2] += (uint32_t)ps[2]; + sum[3] += (uint32_t)ps[3]; + } + // write downsampled pixel: + ARGB32 &dstpix = dst[(y*dstpitch + x+xs)]; + uint32_t out; + uint8_t *pd = (uint8_t *)&out; + int pixels_covered = (sy2-sy1)*(sx2-sx1); + pd[0] = (uint32_t)(sum[0] / pixels_covered); + pd[1] = (uint32_t)(sum[1] / pixels_covered); + pd[2] = (uint32_t)(sum[2] / pixels_covered); + pd[3] = (uint32_t)(sum[3] / pixels_covered); +#ifdef NO_MMX + dstpix = Blenders::BLEND_ADJ3(dstpix, out, alpha); +#else + dstpix = Blenders::BLEND_ADJ3_MMX(dstpix, out, alpha); +#endif + } + } +} + +static wchar_t skinBitmapBlankName[] = L""; +SkinBitmap::SkinBitmap(HINSTANCE hInstance, int id, const wchar_t *forcegroup) +{ + high_quality_resampling = false; + references = 1; + bitmapname = skinBitmapBlankName; + subimage_w = -1; + subimage_h = -1; + x_offset = -1; + y_offset = -1; + fullimage_w = fullimage_h = 0; + has_alpha = 0; + ASSERT(hInstance != NULL); + ownbits = 1; + fromskin = 0; + bits = WASABI_API_IMGLDR->imgldr_makeBmp(hInstance, id,&has_alpha,&fullimage_w,&fullimage_h, forcegroup); + last_failed = 0; + if (bits == NULL) + { + //last_failed = 1; + //TODO: bits = WASABI_API_IMGLDR->imgldr_requestSkinBitmap(ERRORBMP, &has_alpha, &x_offset, &y_offset, &subimage_w, &subimage_h, &fullimage_w, &fullimage_h,_cached); + } + if (bits == NULL) + { + last_failed = 1; + bits = WASABI_API_IMGLDR->imgldr_makeBmp(HARDERRORBMP, &has_alpha, &fullimage_w, &fullimage_h); + } +} + +SkinBitmap::SkinBitmap(ARGB32 *_bits, int w, int h, bool own) +{ + high_quality_resampling = false; + references = 1; + subimage_w = -1; + subimage_h = -1; + x_offset = -1; + y_offset = -1; + bitmapname = skinBitmapBlankName; + fullimage_w = w; + fullimage_h = h; + has_alpha = 1; + if (own) + ownbits = OWNBITS_USECFREE; + else + ownbits = OWNBITS_NOTOURS; + bits = _bits; + fromskin = 0; + last_failed = 0; +} + +// TODO: benski> could we be using GetDIBits here? +void SkinBitmap::bmpToBits(HBITMAP hbmp, HDC defaultDC) +{ +#ifdef WIN32 + if (hbmp && !bits) + { + BITMAPINFO srcbmi={0}; + HDC hMemDC, hMemDC2; + HBITMAP hprev,hprev2=0; + HBITMAP hsrcdib; + void *srcdib; + BITMAP bm; + int r = GetObject(hbmp, sizeof(BITMAP), &bm); + ASSERT(r != 0); + + fullimage_w=bm.bmWidth; + fullimage_h=ABS(bm.bmHeight); + + int bmw=getWidth(); + int bmh=getHeight(); + int xo=getX(); + int yo=getY(); + + srcbmi.bmiHeader.biSize=sizeof(srcbmi.bmiHeader); + srcbmi.bmiHeader.biWidth=bmw; + srcbmi.bmiHeader.biHeight=-bmh; + srcbmi.bmiHeader.biPlanes=1; + srcbmi.bmiHeader.biBitCount=32; + srcbmi.bmiHeader.biCompression=BI_RGB; + hMemDC = CreateCompatibleDC(NULL); + hsrcdib=CreateDIBSection(hMemDC,&srcbmi,DIB_RGB_COLORS,&srcdib,NULL,0); + ASSERTPR(hsrcdib != 0, "CreateDIBSection() failed #6"); + if (defaultDC) + hMemDC2 = defaultDC; + else + { + hMemDC2 = CreateCompatibleDC(NULL); + hprev2 = (HBITMAP) SelectObject(hMemDC2, hbmp); + } + hprev = (HBITMAP) SelectObject(hMemDC, hsrcdib); + BitBlt(hMemDC,0,0,bmw,bmh,hMemDC2,xo,yo,SRCCOPY); + SelectObject(hMemDC, hprev); + if (!defaultDC) + { + SelectObject(hMemDC2, hprev2); + DeleteDC(hMemDC2); + } + DeleteDC(hMemDC); + bits=(ARGB32*)MALLOC(bmw*bmh*4); + if (getHeight()+getY() > bm.bmHeight || getWidth()+getX() > bm.bmWidth) + { + ASSERTALWAYS(StringPrintf("Subbitmap coordinates outside master bitmap [%d,%d,%d,%d in 0,0,%d,%d]", getX(), getY(), getWidth(), getHeight(), bm.bmWidth, bm.bmHeight)); + } + MEMCPY32(bits,srcdib,bmw*bmh/**sizeof(ARGB32)*/); + DeleteObject(hsrcdib); + x_offset=-1; + y_offset=-1; + subimage_w=-1; + subimage_h=-1; + fullimage_w=bmw; + fullimage_h=bmh; + } +#endif +#ifdef LINUX + if (! bits) + { + fullimage_w=hbmp.bmWidth; + fullimage_h=ABS(hbmp.bmHeight); + + bits=(ARGB32*)MALLOC_(fullimage_w * fullimage_h * 4); + MEMCPY32(bits, hbmp.shmseginfo->shmaddr, fullimage_w * fullimage_h); + x_offset=-1; + y_offset=-1; + subimage_w=-1; + subimage_h=-1; + } +#endif +} + +SkinBitmap::SkinBitmap(const wchar_t *elementname, int _cached) +{ + ASSERT(elementname!= NULL); + + high_quality_resampling=false; + references=1; + bitmapname = _wcsdup(elementname); + x_offset = -1; + y_offset = -1; + subimage_w = -1; + subimage_h = -1; + fullimage_w = fullimage_h = 0; + ownbits = OWNBITS_USEIMGLDR; + bits = NULL; + fromskin = 0; + last_failed = 0; + + if (WASABI_API_IMGLDR) // someone might be using us in Classic Skin so explicitly check this + { + 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); + + if (bits == NULL) + bits = WASABI_API_IMGLDR->imgldr_makeBmp(elementname, &has_alpha, &fullimage_w, &fullimage_h); + + 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; + } + + 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) + { + DebugStringW(L"element not found ! %s\n", elementname); + int n = 10*10; + bits = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc(n * sizeof(ARGB32)); + fromskin = OWNBITS_USESYSFREE; + ARGB32 *p = bits; + while (n--) + *p++ = 0xFFFF00FF; + } + } + else + last_failed = 1; +} + +SkinBitmap::SkinBitmap(HBITMAP bitmap) +{ +#ifdef WIN32 + ASSERT(bitmap != NULL); +#endif + high_quality_resampling = false; + references = 1; + subimage_w = -1; + subimage_h = -1; + x_offset = -1; + y_offset = -1; + bitmapname = skinBitmapBlankName; + fullimage_w = fullimage_h = 0; + has_alpha = 0; + ownbits = OWNBITS_USESTDFREE; + bits = NULL; + fromskin = 0; + last_failed = 0; + bmpToBits(bitmap,NULL); +} + +SkinBitmap::SkinBitmap(HBITMAP bitmap, HDC dc, int _has_alpha, void *_bits) +{ + high_quality_resampling=false; + references=1; + subimage_w=-1; + subimage_h=-1; + x_offset=-1; + y_offset=-1; + fromskin = 0; + last_failed = 0; + bitmapname = skinBitmapBlankName; + fullimage_w=fullimage_h=0; +#ifdef WIN32 + ASSERT(bitmap != NULL); +#endif + has_alpha = _has_alpha; + bits = (ARGB32*)_bits; + if (!_bits) + { + ownbits = OWNBITS_USESTDFREE; + bmpToBits(bitmap,dc); + } + else + { +#ifdef WIN32 + BITMAP bm; + ownbits = OWNBITS_NOTOURS; + int r = GetObject(bitmap, sizeof(BITMAP), &bm); + ASSERT(r != 0); + fullimage_w = bm.bmWidth; + fullimage_h = ABS(bm.bmHeight); +#endif +#ifdef LINUX + ownbits = OWNBITS_NOTOURS; + fullimage_w = bitmap.bmWidth; + fullimage_h = ABS(bitmap.bmHeight); +#endif +//port me + } +} + +SkinBitmap::SkinBitmap(ifc_canvas *canvas) +{ + high_quality_resampling=false; + references=1; + subimage_w=-1; + subimage_h=-1; + x_offset=-1; + y_offset=-1; + bits = NULL; + + void *canvas_bits = canvas->getBits(); + if (canvas_bits) + { + canvas->getDim(&subimage_w, &fullimage_h, &fullimage_w); + fullimage_w/=4; + canvas->getOffsets(&x_offset, &y_offset); + size_t copylen = fullimage_h*fullimage_w*sizeof(ARGB32); + bits =(ARGB32 *)MALLOC(copylen); + memcpy(bits, canvas_bits, copylen); + last_failed = 0; + ownbits = OWNBITS_USESTDFREE; + } + else + { + last_failed = 1; + ownbits = OWNBITS_NOTOURS; + } + subimage_h=-1; + bitmapname = skinBitmapBlankName; + has_alpha = 1; + fromskin = 0; +} + +SkinBitmap::SkinBitmap(int w, int h, ARGB32 bgcolor) +{ + high_quality_resampling=false; + references=1; + subimage_w=-1; + subimage_h=-1; + x_offset=-1; + y_offset=-1; + fullimage_w=w; + bitmapname = skinBitmapBlankName; + fullimage_h=h; + fromskin = 0; + last_failed = 0; + + int memsize = w*h*sizeof(ARGB32); + if (memsize == 0) memsize++; // +1 so no failure when 0x0 + bits = (ARGB32*)MALLOC(memsize); + + DWORD *dw = (DWORD *)bits; + MEMFILL<DWORD>(dw, bgcolor, w*h); + + has_alpha = TRUE; + ownbits = OWNBITS_USESTDFREE; // 2 specifies should be FREE()'d +} + +SkinBitmap::~SkinBitmap() +{ + if (bits) + { + switch(ownbits) + { + case OWNBITS_USESTDFREE: + FREE(bits); + break; + case OWNBITS_USECFREE: + free(bits); + break; + case OWNBITS_USESYSFREE: + WASABI_API_MEMMGR->sysFree(bits); + break; + case OWNBITS_USEIMGLDR: + { + if (WASABI_API_IMGLDR) + { + if (fromskin) + WASABI_API_IMGLDR->imgldr_releaseSkinBitmap(bits); + else +#ifndef _WASABIRUNTIME + WASABI_API_IMGLDR->imgldr_releaseBmp(bits); +#else + WASABI_API_IMGLDR->imgldr_releaseSkinBitmap(bits); +#endif + } + } + break; + } + } + bits = NULL; + + if (bitmapname && bitmapname != skinBitmapBlankName) + free(bitmapname); +} + +void SkinBitmap::blit(ifc_canvas *canvas, int x, int y) +{ + RECT src, dst; + src.left=0; + src.top=0; + src.bottom=getHeight(); + src.right=getWidth(); + dst.left=x; + dst.right=x+getWidth(); + dst.top=y; + dst.bottom=y+getHeight(); + blitToRect(canvas,&src,&dst,255); +} + +void SkinBitmap::blitRectToTile(ifc_canvas *canvas, RECT *dest, RECT *src, int xoffs, int yoffs, int alpha) +{ + int startx,starty; + + int w,h; + + w = src->right-src->left; + h = src->bottom-src->top; + if (w <= 0 || h <= 0) return; //wtfmf + + RECT c; + if (canvas->getClipBox(&c) == NULLREGION) + { + c = *dest; + } + else + { + if (dest->left > c.left) c.left = dest->left; + if (dest->top > c.top) c.top = dest->top; + if (dest->right < c.right) c.right = dest->right; + if (dest->bottom < c.bottom) c.bottom = dest->bottom; + } + + + starty = c.top-((c.top - dest->top) % h)- yoffs; + startx = c.left-((c.left - dest->left) % w) - xoffs; + + for (int j=starty;j<c.bottom;j+=h) + for (int i=startx;i<c.right;i+=w) + { + int xp=i; + int yp=j; + int xo=0; + int yo=0; + int _w=getWidth(); + int _h=getHeight(); + if (xp < c.left) + { + xo=c.left-xp; + _w+=xo; + xp=c.left; + } + if (yp < c.top) + { + yo=c.top-yp; + _h+=yo; + yp=c.top; + } + if (xp + _w >= c.right) _w=c.right-xp; + if (yp + _h >= c.bottom) _h=c.bottom-yp; + RECT _s={xo, yo, xo+_w, yo+_h}; + RECT _d={xp, yp, xp+_w, yp+_h}; + blitToRect(canvas, &_s, &_d, alpha); + } +} + + +void SkinBitmap::blitTile(ifc_canvas *canvas, RECT *dest, int xoffs, int yoffs, int alpha) +{ + RECT r={0,0,getWidth(),getHeight()}; + blitRectToTile(canvas, dest, &r, xoffs, yoffs, alpha); +} + +#ifdef WIN32 +#pragma warning(push) +#pragma warning(disable : 4799) +#endif + + +#define DEFAULT_CACHE_WIDTH 64 +#define DEFAULT_CACHE_HEIGHT 64 + +extern DWORD bitmap_cache_tls; + +void SkinBitmap::blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha) // only dst(top,left) are used +{ + if (alpha <= 0) return; + if (alpha > 255) alpha = 255; + + BltCanvas *blitToRectCanvas=0; + HDC hdc = canvas->getHDC(); + if (hdc == NULL) return; + void *dib=canvas->getBits(); + int cwidth,cheight, pitch; + BaseCloneCanvas clone(canvas); + bool usingBlitCanvas = false; + RECT destrect=*dst; + destrect.bottom=destrect.top+(src->bottom-src->top); + destrect.right=destrect.left+(src->right-src->left); + + RECT c; + int ctype=canvas->getClipBox(&c); + + if (c.top > destrect.top) destrect.top=c.top; + if (c.left > destrect.left) destrect.left=c.left; + if (c.bottom < destrect.bottom) destrect.bottom=c.bottom; + if (c.right < destrect.right) destrect.right=c.right; + +#ifdef NO_SIMPLEFASTMODE + dib=NULL; +#endif + + if (destrect.right <= destrect.left || destrect.bottom <= destrect.top) return; + int xs,yp,xe,ye; + + if (!dib || canvas->getDim(NULL,&cheight,&cwidth) || !cwidth || cheight < 1 || ctype == COMPLEXREGION) + { + cwidth=destrect.right-destrect.left; + cheight=destrect.bottom-destrect.top; + +/* create cached canvas for this thread if it doesn't exist */ + blitToRectCanvas = (BltCanvas *)TlsGetValue(bitmap_cache_tls); + if (!blitToRectCanvas) + { + blitToRectCanvas = new BltCanvas(cwidth, cheight); + TlsSetValue(bitmap_cache_tls, (LPVOID)blitToRectCanvas); + } + int cacheWidth, cacheHeight; + blitToRectCanvas->getDim(&cacheWidth, &cacheHeight, NULL); + + /* resize cache if necessary */ + if (cwidth > cacheWidth || cheight > cacheHeight) + { + cacheWidth=MAX(cacheWidth, cwidth); + cacheHeight=MAX(cacheHeight, cheight); + blitToRectCanvas->DestructiveResize(cacheWidth, cacheHeight); + } + + dib = blitToRectCanvas->getBits(); + if (has_alpha || alpha < 255) + clone.blit(destrect.left, destrect.top, blitToRectCanvas, 0, 0, cwidth, cheight); + + xs=0; + yp=0; + xe=cwidth; + ye=cheight; + pitch=cacheWidth; + usingBlitCanvas = true; + } + else + { + xs=destrect.left; + xe=destrect.right; + yp=destrect.top; + ye=destrect.bottom; + + cwidth/=4; + pitch=cwidth; + } + int xpo=(dst->left-destrect.left+xs)-(getX()+src->left); + int ypo=(dst->top-destrect.top+yp)-(getY()+src->top); + + if (yp < 0) yp=0; + if (xs < 0) xs=0; + + if (yp<getY()+ypo) yp=ypo+getY(); + if (xs<getX()+xpo) xs=xpo+getX(); + + if (xe > getWidth()+getX()+xpo) xe=getWidth()+getX()+xpo; + if (ye > getHeight()+getY()+ypo) ye=getHeight()+getY()+ypo; + + // blend bitmap to dib + + if (xs<xe) for (; yp < ye; yp ++) + { + int xp=xe-xs; + unsigned int *dest=((unsigned int*)dib) + pitch*yp + xs; + unsigned int *src=((unsigned int*)bits) + (yp-ypo)*fullimage_w + (xs-xpo); + + if (!has_alpha && alpha==255) // simple copy + { + MEMCPY32(dest,src,xp); + } + else if (!has_alpha) // no alpha channel info, but just a simple blend + { + if (!HAS_MMX) + while (xp--) *dest++ = Blenders::BLEND_ADJ1(*src++, *dest, alpha); + +#ifndef NO_MMX + else + { +#ifdef WIN32 + if (xp>1) __asm + { + movd mm3, [alpha] + mov ecx, xp + + movq mm4, [SkinBitmap_mmx_revn2] + packuswb mm3, mm3 // 0000HHVV + + paddusw mm3, [SkinBitmap_mmx_one] + mov edi, dest + + punpcklwd mm3, mm3 // HHVVHHVV + mov esi, src + + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + shr ecx, 1 + + psubw mm4, mm3 + + align 16 +_blitAlpha_Loop1: + + movd mm0, [edi] + + movd mm1, [esi] + punpcklbw mm0, [SkinBitmap_mmx_zero] + + movd mm7, [edi+4] + punpcklbw mm1, [SkinBitmap_mmx_zero] + + pmullw mm0, mm4 + pmullw mm1, mm3 + + movd mm6, [esi+4] + punpcklbw mm7, [SkinBitmap_mmx_zero] + + punpcklbw mm6, [SkinBitmap_mmx_zero] + + pmullw mm7, mm4 + pmullw mm6, mm3 + + paddw mm0, mm1 + + psrlw mm0, 8 + + packuswb mm0, mm0 + add esi, 8 + + movd [edi], mm0 + paddw mm7, mm6 + + psrlw mm7, 8 + + packuswb mm7, mm7 + + movd [edi+4], mm7 + + add edi, 8 + + dec ecx + jnz _blitAlpha_Loop1 + mov src, esi + mov dest, edi +#else + if (xp > 1) + { + __asm__ volatile( + "movd %6, %%mm3\n" + "mov %2, %%ecx\n" + "movq (SkinBitmap_mmx_revn2), %%mm4\n" + "packuswb %%mm3, %%mm3\n" + "paddusw (SkinBitmap_mmx_one), %%mm3\n" + "mov %0, %%edi\n" + "punpcklwd %%mm3, %%mm3\n" + "mov %1, %%esi\n" + "punpckldq %%mm3, %%mm3\n" + "shr $1, %%ecx\n" + "psubw %%mm3, %%mm4\n" + ".align 16\n" + "_blitAlpha_Loop1:\n" + "movd (%%edi), %%mm0\n" + "movd (%%esi), %%mm1\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n" + "movd 4(%%edi), %%mm7\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n" + "pmullw %%mm3, %%mm0\n" + "pmullw %%mm4, %%mm1\n" + "movd 4(%%esi), %%mm6\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n" + "pmullw %%mm4, %%mm6\n" + "pmullw %%mm3, %%mm7\n" + "paddw %%mm1, %%mm0\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "add $8, %%esi\n" + "movd %%mm0, (%%edi)\n" + "paddw %%mm6, %%mm7\n" + "psrlw $8, %%mm7\n" + "packuswb %%mm7, %%mm7\n" + "movd %%mm7, 4(%%edi)\n" + "add $8, %%edi\n" + "dec %%ecx\n" + "jnz _blitAlpha_Loop1\n" + "mov %%esi, %1\n" + "mov %%edi, %0\n" + + : "=m"(dest), "=m"(src), "=m"(xp) + : "0"(dest), "1"(src), "2"(xp), "m"(alpha) + : "%eax", "%ecx", "%esi", "%edi"); + +#endif + } + if (xp & 1) *dest++ = Blenders::BLEND_ADJ1_MMX(*src++, *dest, alpha); + } // mmx available +#endif // !NO_MMX + } + else if (alpha == 255) // no global alpha, just alpha channel + { + if (!HAS_MMX) + while (xp--) *dest++ = Blenders::BLEND_ADJ2(*dest, *src++); + +#ifndef NO_MMX + else + { +#ifdef WIN32 + if (xp > 1) __asm + { + mov ecx, xp + shr ecx, 1 + mov edi, dest + mov esi, src + align 16 +_blitAlpha_Loop2: + + movd mm3, [esi] + movd mm5, [esi+4] + + movq mm2, [SkinBitmap_mmx_revn2] + psrld mm3, 24 + + movq mm4, [SkinBitmap_mmx_revn2] + psrld mm5, 24 + + movd mm0, [edi] + packuswb mm3, mm3 // 0000HHVV + + movd mm1, [esi] + packuswb mm5, mm5 // 0000HHVV + + movd mm6, [esi+4] + paddusw mm3, [SkinBitmap_mmx_one] + + punpcklwd mm3, mm3 // HHVVHHVV + paddusw mm5, [SkinBitmap_mmx_one] + + movd mm7, [edi+4] + punpcklwd mm5, mm5 // HHVVHHVV + + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + punpckldq mm5, mm5 // HHVVHHVV HHVVHHVV + + punpcklbw mm6, [SkinBitmap_mmx_zero] + psubw mm4, mm5 + + punpcklbw mm0, [SkinBitmap_mmx_zero] + psubw mm2, mm3 + + punpcklbw mm7, [SkinBitmap_mmx_zero] + pmullw mm0, mm2 + + pmullw mm7, mm4 + punpcklbw mm1, [SkinBitmap_mmx_zero] + + psubw mm2, mm3 + + psrlw mm0, 8 + psrlw mm7, 8 + paddw mm0, mm1 + + paddw mm7, mm6 + packuswb mm0, mm0 + + movd [edi], mm0 + packuswb mm7, mm7 + + movd [edi+4], mm7 + + add esi, 8 + add edi, 8 + + dec ecx + jnz _blitAlpha_Loop2 + mov src, esi + mov dest, edi +#else + if (xp > 1) + { + __asm__ volatile( + "mov %4, %%ecx\n" + "shr $1, %%ecx\n" + "mov %0, %%edi\n" + "mov %1, %%esi\n" + ".align 16\n" + "_blitAlpha_Loop2:\n" + "movd (%%esi), %%mm3\n" + "movd 4(%%esi), %%mm5\n" + "movq (SkinBitmap_mmx_revn2), %%mm2\n" + "psrld $24, %%mm3\n" + "movq (SkinBitmap_mmx_revn2), %%mm4\n" + "psrld $24, %%mm5\n" + "movd (%%edi), %%mm0\n" + "packuswb %%mm3, %%mm3\n" + "movd (%%esi), %%mm1\n" + "packuswb %%mm5, %%mm5\n" + "movd 4(%%esi), %%mm6\n" + "paddusw (SkinBitmap_mmx_one), %%mm3\n" + "punpcklwd %%mm3, %%mm3\n" + "paddusw (SkinBitmap_mmx_one), %%mm5\n" + "movd 4(%%edi), %%mm7\n" + "punpcklwd %%mm5, %%mm5\n" + "punpckldq %%mm3, %%mm3\n" + "punpckldq %%mm5, %%mm5\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n" + "psubw %%mm5, %%mm4\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n" + "psubw %%mm3, %%mm2\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n" + "pmullw %%mm2, %%mm0\n" + "pmullw %%mm4, %%mm7\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n" + "psubw %%mm3, %%mm2\n" + "psrlw $8, %%mm0\n" + "psrlw $8, %%mm7\n" + "paddw %%mm1, %%mm0\n" + "paddw %%mm6, %%mm7\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, (%%edi)\n" + "packuswb %%mm7, %%mm7\n" + "movd %%mm7, 4(%%edi)\n" + "add $8, %%esi\n" + "add $8, %%edi\n" + "dec %%ecx\n" + "jnz _blitAlpha_Loop2\n" + "mov %%esi, %1\n" + "mov %%edi, %0\n" + + : "=m"(dest), "=m"(src) + : "0"(dest), "1"(src), "m"(xp) + : "%eax", "%ecx", "%esi", "%edi"); +#endif + } + if (xp&1) *dest++ = Blenders::BLEND_ADJ2_MMX(*dest, *src++); + } // HAS_MMX +#endif // ifndef NO_MMX + } + else // both + { + if (!HAS_MMX) + while (xp--) *dest++ = Blenders::BLEND_ADJ3(*dest, *src++, alpha); +#ifndef NO_MMX + else + { +#ifdef WIN32 + if (xp > 1) __asm + { + movd mm5, [alpha] + mov ecx, xp + + packuswb mm5, mm5 + shr ecx, 1 + + paddusw mm5, [SkinBitmap_mmx_one] + + punpcklwd mm5, mm5 + mov edi, dest + + punpckldq mm5, mm5 + mov esi, src + + align 16 +_blitAlpha_Loop3: + + movd mm3, [esi] // VVVVVVVV + movd mm4, [esi+4] // VVVVVVVV + + movd mm0, [edi] + psrld mm3, 24 + + movd mm1, [esi] + psrld mm4, 24 + + paddusw mm3, [SkinBitmap_mmx_one] + paddusw mm4, [SkinBitmap_mmx_one] + + movd mm7, [edi+4] + punpcklwd mm3, mm3 + + movd mm6, [esi+4] + punpcklwd mm4, mm4 + + punpckldq mm3, mm3 + punpckldq mm4, mm4 + + pmullw mm3, mm5 + pmullw mm4, mm5 + + punpcklbw mm7, [SkinBitmap_mmx_zero] + punpcklbw mm6, [SkinBitmap_mmx_zero] + + movq mm2, [SkinBitmap_mmx_revn2] + psrlw mm3, 8 + + psrlw mm4, 8 + + punpcklbw mm0, [SkinBitmap_mmx_zero] + punpcklbw mm1, [SkinBitmap_mmx_zero] + + psubw mm2, mm3 + pmullw mm0, mm2 + + pmullw mm1, mm5 + add esi, 8 + + movq mm2, [SkinBitmap_mmx_revn2] + pmullw mm6, mm5 + + paddusw mm0, mm1 + psubw mm2, mm4 + + pmullw mm7, mm2 + psrlw mm0, 8 + + packuswb mm0, mm0 + paddusw mm7, mm6 + + movd [edi], mm0 + psrlw mm7, 8 + + packuswb mm7, mm7 + + movd [edi+4], mm7 + + add edi, 8 + + dec ecx + jnz _blitAlpha_Loop3 + mov src, esi + mov dest, edi +#else + if (xp > 1) + { + __asm__ volatile( + "movd %5, %%mm5\n" + "mov %4, %%ecx\n" + "packuswb %%mm5, %%mm5 \n" + "shr $1, %%ecx\n" + "paddusw (SkinBitmap_mmx_one), %%mm5\n" + "punpcklwd %%mm5, %%mm5\n" + "mov %0, %%edi\n" + "punpckldq %%mm5, %%mm5\n" + "mov %1, %%esi\n" + ".align 16\n" + "_blitAlpha_Loop3:\n" + "movd (%%esi), %%mm3\n" + "movd 4(%%esi), %%mm4\n" + "movd (%%edi), %%mm0\n" + "psrld $24, %%mm3\n" + "movd (%%esi), %%mm1\n" + "psrld $24, %%mm4\n" + "paddusw (SkinBitmap_mmx_one), %%mm3\n" + "paddusw (SkinBitmap_mmx_one), %%mm4\n" + "movd 4(%%edi), %%mm7\n" + "punpcklwd %%mm3, %%mm3\n" + "movd 4(%%esi), %%mm6\n" + "punpcklwd %%mm4, %%mm4\n" + "punpckldq %%mm3, %%mm3\n" + "punpckldq %%mm4, %%mm4\n" + "pmullw %%mm5, %%mm3\n" + "pmullw %%mm5, %%mm4\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n" + "movq (SkinBitmap_mmx_revn2), %%mm2\n" + "psrlw $8, %%mm3\n" + "psrlw $8, %%mm4\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n" + "psubw %%mm3, %%mm2\n" + "pmullw %%mm2, %%mm0\n" + "pmullw %%mm5, %%mm1\n" + "add $8, %%esi\n" + "movq (SkinBitmap_mmx_revn2), %%mm2\n" + "pmullw %%mm5, %%mm6\n" + "paddusw %%mm1, %%mm0\n" + "psubw %%mm4, %%mm2\n" + "pmullw %%mm2, %%mm7\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "paddusw %%mm6, %%mm7\n" + "movd %%mm0, (%%edi)\n" + "psrlw $8, %%mm7\n" + "packuswb %%mm7, %%mm7\n" + "movd %%mm7, 4(%%edi)\n" + "add $8, %%edi\n" + "dec %%ecx\n" + "jnz _blitAlpha_Loop3\n" + "mov %%esi, %1\n" + "mov %%edi, %0\n" + + : "=m"(dest), "=m"(src) + : "0"(dest), "1"(src), "m"(xp), "m"(alpha) + : "%eax", "%ecx", "%esi", "%edi"); +#endif + } + if (xp&1) *dest++ = Blenders::BLEND_ADJ3_MMX(*dest, *src++, alpha); + } // HAS_MMX +#endif // ifndef NO_MMX + } + } +#ifndef NO_MMX + Blenders::BLEND_MMX_END(); +#endif + // write bits back to dib. + + if (usingBlitCanvas) + { + blitToRectCanvas->blit(0, 0, &clone, destrect.left, destrect.top, cwidth, cheight); + } +} + +#ifdef WIN32 +#pragma warning(pop) +#endif + +void SkinBitmap::stretch(ifc_canvas *canvas, int x, int y, int w, int h) +{ + RECT src, dst; + src.left=0; + src.top=0; + src.right=getWidth(); + src.bottom=getHeight(); + dst.left=x; + dst.right=x+w; + dst.top=y; + dst.bottom=y+h; + stretchToRectAlpha(canvas,&src,&dst,255); +} + +void SkinBitmap::stretchToRect(ifc_canvas *canvas, RECT *r) +{ + stretch(canvas, r->left, r->top, r->right - r->left, r->bottom - r->top); +} + +void SkinBitmap::stretchRectToRect(ifc_canvas *canvas, RECT *src, RECT *dst) +{ + stretchToRectAlpha(canvas,src,dst,255); +} + + +void SkinBitmap::stretchToRectAlpha(ifc_canvas *canvas, RECT *r, int alpha) +{ + RECT re; + re.left=0; re.top=0; + re.right=getWidth(); re.bottom=getHeight(); + stretchToRectAlpha(canvas,&re,r,alpha); +} + +void SkinBitmap::blitAlpha(ifc_canvas *canvas, int x, int y, int alpha) +{ + RECT dst,src; + dst.left=x; + dst.top=y; + src.left=0; + src.top=0; + src.bottom=getHeight(); + src.right=getWidth(); + blitToRect(canvas,&src,&dst,alpha); +} + +#ifdef WIN32 +#pragma warning(push) +#pragma warning(disable : 4799) +#endif + +template <class C> +class Stretcher +{ +public: + static void _stretchToRectAlpha(SkinBitmap *bitmap, int ys, int ye, int xe, int xs, int xstart, int yv, void *dib, int pitch, int dxv, int dyv, int alpha) + { + int bitmap_x = bitmap->getX(); + int bitmap_y = bitmap->getY(); + int bmpheight = bitmap->getHeight(); + int fullimage_w = bitmap->getFullWidth(); + void *bits = bitmap->getBits(); + int xp=xe-xs; + for (int yp = ys; yp < ye; yp ++) + { + int t=yv>>16; + if (t < 0) t=0; + if (t >= bmpheight) t=bmpheight-1; + int *psrc=((int*)bits) + (t+bitmap_y)*fullimage_w + bitmap_x; + int *dest=((int*)dib) + pitch*yp + xs; + + C::stretch(xp, psrc, dest, xstart, dxv, alpha); + + yv+=dyv; + } + } +}; + +// no alpha, just stretch +class Stretch +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { + while (xp--) //JFtodo: assembly optimize - these first two modes aren't used that much anyway + { + *dest++ = psrc[xv>>16]; + xv+=dxv; + } + } +}; + +// no alpha channel, just a global alpha val +class StretchGlobal +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { + while (xp--) //JFTODO: make MMX optimized version + { + *dest++ = Blenders::BLEND_ADJ1(psrc[xv>>16], *dest, alpha); + xv+=dxv; + } + } +}; + +// alpha channel, no global alpha val +class StretchChannel +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { + while (xp--) + { + *dest++ = Blenders::BLEND_ADJ2(*dest, psrc[xv>>16]); + xv+=dxv; + } + } +}; + +class StretchGlobalChannel +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { + while (xp--) + { + *dest++ = Blenders::BLEND_ADJ3(*dest, psrc[xv>>16], alpha); + xv+=dxv; + } + } +}; + + +#ifndef NO_MMX + +// no alpha channel, just a global alpha val +class StretchGlobalMMX +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { + while (xp--) //JFTODO: make MMX optimized version + { + *dest++ = Blenders::BLEND_ADJ1_MMX(psrc[xv>>16], *dest, alpha); + xv+=dxv; + } + } +}; + + +// alpha channel, no global alpha val +class StretchChannelMMX +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { +#ifdef WIN32 + if (xp>1) __asm + { + mov ecx, xp + mov edi, dest + + shr ecx, 1 + mov esi, psrc + + mov edx, xv + mov ebx, dxv + + align 16 +_stretchAlpha_Loop2: + + mov eax, edx + movd mm0, [edi] + + movq mm4, [SkinBitmap_mmx_revn2] + shr eax, 16 + + movq mm2, [SkinBitmap_mmx_revn2] + punpcklbw mm0, [SkinBitmap_mmx_zero] + + movd mm3, [esi+eax*4] + movd mm1, [esi+eax*4] + + lea eax, [edx+ebx] + shr eax, 16 + + movd mm7, [edi+4] + psrld mm3, 24 + + packuswb mm3, mm3 // 0000HHVV + movd mm5, [esi+eax*4] + + movd mm6, [esi+eax*4] + psrld mm5, 24 + + paddusw mm3, [SkinBitmap_mmx_one] + punpcklbw mm6, [SkinBitmap_mmx_zero] + + packuswb mm5, mm5 // 0000HHVV + lea edx, [edx+ebx*2] + + paddusw mm5, [SkinBitmap_mmx_one] + punpcklwd mm3, mm3 // HHVVHHVV + + punpcklwd mm5, mm5 // HHVVHHVV + add edi, 8 + + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + + punpckldq mm5, mm5 // HHVVHHVV HHVVHHVV + + psubw mm4, mm5 + + psubw mm2, mm3 + + punpcklbw mm7, [SkinBitmap_mmx_zero] + pmullw mm0, mm2 + + pmullw mm7, mm4 + punpcklbw mm1, [SkinBitmap_mmx_zero] + + psubw mm2, mm3 + + psrlw mm0, 8 + psrlw mm7, 8 + paddw mm0, mm1 + + paddw mm7, mm6 + packuswb mm0, mm0 + + movd [edi-8], mm0 + packuswb mm7, mm7 + + movd [edi-4], mm7 + + dec ecx + jnz _stretchAlpha_Loop2 + mov dest, edi + mov xv, edx + } +#else + if (xp>1) + { + __asm__ volatile( + "mov %5, %%ecx\n" + "mov %0, %%edi\n" + "shr $1, %%ecx\n" + "mov %1, %%esi\n" + "mov %2, %%edx\n" + "mov %7, %%ebx\n" + ".align 16\n" + "_stretchAlpha_Loop2:\n" + "mov %%edx, %%eax\n" + "movd (%%edi), %%mm0\n" + "movq (SkinBitmap_mmx_revn2), %%mm4\n" + "shr $16, %%eax\n" + "movq (SkinBitmap_mmx_revn2), %%mm2\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n" + "movd (%%esi,%%eax,4), %%mm3\n" + "movd (%%esi,%%eax,4), %%mm1\n" + "lea (%%edx,%%ebx), %%eax\n" + "shr $16, %%eax\n" + "movd 4(%%edi), %%mm7\n" + "psrld $24, %%mm3\n" + "packuswb %%mm3, %%mm3\n" + "movd (%%esi,%%eax,4), %%mm5\n" + "movd (%%esi,%%eax,4), %%mm6\n" + "psrld $24, %%mm5\n" + "paddusw (SkinBitmap_mmx_one), %%mm3\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n" + "packuswb %%mm5, %%mm5\n" + "lea (%%edx,%%ebx,2), %%edx\n" + "paddusw (SkinBitmap_mmx_one), %%mm5\n" + "punpcklwd %%mm3, %%mm3\n" + "punpcklwd %%mm5, %%mm5\n" + "add $8, %%edi\n" + "punpckldq %%mm3, %%mm3\n" + "punpckldq %%mm5, %%mm5\n" + "psubw %%mm5, %%mm4\n" + "psubw %%mm3, %%mm2\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n" + "pmullw %%mm2, %%mm0\n" + "pmullw %%mm4, %%mm7\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n" + "psubw %%mm3, %%mm2\n" + "psrlw $8, %%mm0\n" + "psrlw $8, %%mm7\n" + "paddw %%mm1, %%mm0\n" + "paddw %%mm6, %%mm7\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, -8(%%edi)\n" + "packuswb %%mm7, %%mm7\n" + "movd %%mm7, -4(%%edi)\n" + "dec %%ecx\n" + "jnz _stretchAlpha_Loop2\n" + "mov %%edi, %0\n" + "mov %%edx, %2\n" + + : "=m"(dest), "=m"(psrc), "=m"(xv) + : "0"(dest), "1"(psrc), "m"(xp), + "2"(xv), "m"(dxv), "m"(alpha) + : "%eax", "%ebx", "%ecx", "%edx", + "%esi", "%edi"); + + } +#endif + + if (xp&1) *dest++ = Blenders::BLEND_ADJ2_MMX(*dest, psrc[xv>>16]); + } +}; + + +class StretchGlobalChannelMMX +{ +public: + static void stretch(int xp, int *psrc, int *dest, int xv, int dxv, int alpha) + { +#ifdef WIN32 + if (xp>1) __asm + { + movd mm5, [alpha] + mov ecx, xp + + packuswb mm5, mm5 + shr ecx, 1 + + paddusw mm5, [SkinBitmap_mmx_one] + + punpcklwd mm5, mm5 + mov edi, dest + + punpckldq mm5, mm5 + mov esi, psrc + + mov edx, xv + mov ebx, dxv + + align 16 +_stretchAlpha_Loop3: + movd mm0, [edi] + mov eax, edx + + movd mm7, [edi+4] + shr eax, 16 + + movd mm1, [esi+eax*4] + movd mm3, [esi+eax*4] // VVVVVVVV + + lea eax, [edx+ebx] + psrld mm3, 24 + + paddusw mm3, [SkinBitmap_mmx_one] + + punpcklwd mm3, mm3 + shr eax, 16 + + punpckldq mm3, mm3 + + pmullw mm3, mm5 + + movd mm4, [esi+eax*4] // VVVVVVVV + movd mm6, [esi+eax*4] + + movq mm2, [SkinBitmap_mmx_revn2] + psrld mm4, 24 + + paddusw mm4, [SkinBitmap_mmx_one] + punpcklbw mm7, [SkinBitmap_mmx_zero] + + punpcklwd mm4, mm4 + lea edx, [edx+ebx*2] + + punpckldq mm4, mm4 + add edi, 8 + + punpcklbw mm6, [SkinBitmap_mmx_zero] + pmullw mm4, mm5 + + psrlw mm3, 8 + + punpcklbw mm0, [SkinBitmap_mmx_zero] + + punpcklbw mm1, [SkinBitmap_mmx_zero] + psubw mm2, mm3 + + pmullw mm0, mm2 + pmullw mm1, mm5 + + pmullw mm6, mm5 + psrlw mm4, 8 + + movq mm2, [SkinBitmap_mmx_revn2] + paddusw mm0, mm1 + psubw mm2, mm4 + + pmullw mm7, mm2 + psrlw mm0, 8 + + packuswb mm0, mm0 + paddusw mm7, mm6 + + movd [edi-8], mm0 + psrlw mm7, 8 + + packuswb mm7, mm7 + + movd [edi-4], mm7 + + dec ecx + jnz _stretchAlpha_Loop3 + mov xv, edx + mov dest, edi + } +#else + if (xp>1) + { + __asm__ volatile( + "movd %8, %%mm5\n" + "mov %5, %%ecx\n" + "packuswb %%mm5, %%mm5 \n" + "shr $1, %%ecx\n" + "paddusw (SkinBitmap_mmx_one), %%mm5\n" + "punpcklwd %%mm5, %%mm5\n" + "mov %0, %%edi\n" + "punpckldq %%mm5, %%mm5\n" + "mov %1, %%esi\n" + "mov %6, %%edx\n" + "mov %7, %%ebx\n" + ".align 16\n" + "_stretchAlpha_Loop3:\n" + "movd (%%edi), %%mm0\n" + "mov %%edx, %%eax\n" + "movd 4(%%edi), %%mm7\n" + "shr $16, %%eax\n" + "movd (%%esi,%%eax,4), %%mm1\n" + "movd (%%esi,%%eax,4), %%mm3\n" + "lea (%%edx,%%ebx), %%eax\n" + "psrld $24, %%mm3\n" + "paddusw (SkinBitmap_mmx_one), %%mm3\n" + "punpcklwd %%mm3, %%mm3\n" + "shr $16, %%eax\n" + "punpckldq %%mm3, %%mm3\n" + "pmullw %%mm5, %%mm3\n" + "movd (%%esi,%%eax,4), %%mm4\n" + "movd (%%esi,%%eax,4), %%mm6\n" + "movq (SkinBitmap_mmx_revn2), %%mm2\n" + "psrld $24, %%mm4\n" + "paddusw (SkinBitmap_mmx_one), %%mm4\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm7\n" + "punpcklwd %%mm4, %%mm4\n" + "lea (%%edx,%%ebx,2), %%edx\n" + "punpckldq %%mm4, %%mm4\n" + "add $8, %%edi\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm6\n" + "pmullw %%mm5, %%mm4\n" + "psrlw $8, %%mm3\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm0\n" + "punpcklbw (SkinBitmap_mmx_zero), %%mm1\n" + "psubw %%mm3, %%mm2\n" + "pmullw %%mm2, %%mm0\n" + "pmullw %%mm5, %%mm1\n" + "pmullw %%mm5, %%mm6\n" + "psrlw $8, %%mm4\n" + "movq (SkinBitmap_mmx_revn2), %%mm2\n" + "paddusw %%mm1, %%mm0\n" + "psubw %%mm4, %%mm2\n" + "pmullw %%mm2, %%mm7\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "paddusw %%mm6, %%mm7\n" + "movd %%mm0, -8(%%edi)\n" + "psrlw $8, %%mm7\n" + "packuswb %%mm7, %%mm7\n" + "movd %%mm7, -4(%%edi)\n" + "dec %%ecx\n" + "jnz _stretchAlpha_Loop3\n" + "mov %%edi, %0\n" + "mov %%edx, %2\n" + + : "=m"(dest), "=m"(psrc), "=m"(xv) + : "0"(dest), "1"(psrc), "m"(xp), + "m"(xv), "m"(dxv), "m"(alpha) + : "%eax", "%ebx", "%ecx", "%edx", + "%esi", "%edi"); + + } +#endif + + if (xp&1) *dest++ = Blenders::BLEND_ADJ3_MMX(*dest, psrc[xv>>16], alpha); + } +}; +#endif + + +class __Stretch : public Stretcher<Stretch> {}; +class __StretchGlobal : public Stretcher<StretchGlobal> {}; +class __StretchChannel : public Stretcher<StretchChannel> {}; +class __StretchGlobalChannel : public Stretcher<StretchGlobalChannel> {}; + +#ifndef NO_MMX +class __StretchGlobalMMX : public Stretcher<StretchGlobalMMX> {}; +class __StretchChannelMMX : public Stretcher<StretchChannelMMX> {}; +class __StretchGlobalChannelMMX : public Stretcher<StretchGlobalChannelMMX> {}; +#endif + +#ifdef WIN32 +#pragma warning(pop) +#endif + + +void SkinBitmap::stretchToRectAlpha(ifc_canvas *canvas, RECT *_src, RECT *_dst, int alpha) +{ + + if (alpha <= 0) return; + if (alpha > 255) alpha = 255; + + RECT src=*_src; + RECT dst=*_dst; + + if ((src.right-src.left) == (dst.right-dst.left) && + (src.bottom-src.top) == (dst.bottom-dst.top)) + { + blitToRect(canvas,_src,_dst,alpha); + return; + } + //FG> this is a hack, we should support subpixels instead + if (src.left == src.right) + { + if (src.right < getWidth()) + src.right++; + else + src.left--; + } + if (src.top== src.bottom) + { + if (src.bottom < getHeight()) + src.bottom++; + else + src.top--; + } + + if (src.left >= src.right || src.top >= src.bottom) return; + if (dst.left >= dst.right || dst.top >= dst.bottom) return; + + BltCanvas *blitToRectCanvas=0; + void *dib=canvas->getBits(); + bool usingBlitCanvas = false; + BaseCloneCanvas clone(canvas); + int cwidth, cheight, pitch; + + int dyv=((src.bottom-src.top)<<16)/(dst.bottom-dst.top); + int dxv=((src.right-src.left)<<16)/(dst.right-dst.left); + int yv=(src.top<<16); + int xstart=(src.left<<16); + + RECT c; + int ctype=canvas->getClipBox(&c); + if (c.top > dst.top) + { + yv+=(c.top-dst.top)*dyv; + dst.top=c.top; + } + if (c.left > dst.left) + { + xstart+=(c.left-dst.left)*dxv; + dst.left=c.left; + } + if (c.bottom < dst.bottom) + dst.bottom=c.bottom; + if (c.right < dst.right) + dst.right=c.right; + + if (dst.right <= dst.left || dst.bottom <= dst.top) return; + + int xs,xe,ys,ye; + +#ifdef NO_SIMPLEFASTMODE + dib=NULL; +#endif + if (!dib || canvas->getDim(NULL,&cheight,&cwidth) || !cwidth || cheight < 1 || ctype == COMPLEXREGION) + { + cwidth=dst.right-dst.left; + cheight=dst.bottom-dst.top; + + /* create cached canvas for this thread if it doesn't exist */ + blitToRectCanvas = (BltCanvas *)TlsGetValue(bitmap_cache_tls); + if (!blitToRectCanvas) + { + blitToRectCanvas = new BltCanvas(cwidth, cheight); + TlsSetValue(bitmap_cache_tls, (LPVOID)blitToRectCanvas); + } + int cacheWidth, cacheHeight; + blitToRectCanvas->getDim(&cacheWidth, &cacheHeight, NULL); + + /* resize cache, if necessary */ + if (cwidth > cacheWidth || cheight > cacheHeight) + { + cacheWidth=MAX(cacheWidth, cwidth); + cacheHeight=MAX(cacheHeight, cheight); + blitToRectCanvas->DestructiveResize(cacheWidth, cacheHeight); + } + + dib = blitToRectCanvas->getBits(); + if (has_alpha || alpha < 255) + clone.blit(dst.left, dst.top, blitToRectCanvas, 0, 0, cwidth, cheight); + + xs=0; + ys=0; + xe=cwidth; + ye=cheight; + pitch=cacheWidth; + usingBlitCanvas=true; + } + else + { + xs=dst.left; + xe=dst.right; + ys=dst.top; + ye=dst.bottom; + cwidth/=4; + pitch=cwidth; + } + + // stretch and blend bitmap to dib + + if (xstart < 0) xstart=0; + + // Martin> TODO + // we should separate the stretching from this function and move it to the Shrink() function (avoiding breaks from this fragile class) + // HQSkinBitmap will then override the Shrink funtion in order to apply it's own resizing stuff. + // and if we ever want a new algorithm we can just create a new UltraFastAndCoolSkinBitmap class overriding the function again + + if (xs<xe) + { + if (!has_alpha) // doesn't have alpha channel + { + if (!high_quality_resampling || dxv<65536 || dyv<65536) + { + if (alpha == 255) // no global alpha + { + __Stretch::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + else // has global alpha + { +#ifndef NO_MMX + if (HAS_MMX) + { + __StretchGlobalMMX::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + else +#endif + { + __StretchGlobal::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + } + } + else + { + Shrink(this, ys,ye,xe,xs, xstart,yv, (ARGB32 *)dib, pitch, dxv, dyv, alpha); + } + } + else // has alpha channel + { + // FUCKO: JF> BRENNAN FIX THESE BITCHES :) + if (alpha == 255) // no global alpha + { + if (!high_quality_resampling || dxv<65536 || dyv<65536) + { +#ifndef NO_MMX + if (HAS_MMX) + { + __StretchChannelMMX::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + else +#endif + { + __StretchChannel::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + } + else + { + Shrink(this, ys,ye,xe,xs, xstart,yv, (ARGB32 *)dib, pitch, dxv, dyv, alpha); + } + } + else // has global alpha + { + if (!high_quality_resampling || dxv<65536 || dyv<65536) + { +#ifndef NO_MMX + if (HAS_MMX) + { + __StretchGlobalChannelMMX::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + else +#endif + { + __StretchGlobalChannel::_stretchToRectAlpha(this, ys, ye, xe, xs, xstart, yv, dib, pitch, dxv, dyv, alpha); + } + } + else + { + Shrink(this, ys, ye, xe, xs, xstart, yv, (ARGB32 *)dib, pitch, dxv, dyv,alpha); + } + } + } + } + +#ifndef NO_MMX + Blenders::BLEND_MMX_END(); +#endif + // write bits back to dib. + + if (usingBlitCanvas) + { + blitToRectCanvas->blit(0, 0, &clone, dst.left, dst.top, cwidth, cheight); + } +} + +COLORREF SkinBitmap::getPixel(int x, int y) +{ + ASSERT(bits != NULL); + if (x < 0 || y < 0 || x >= getFullWidth()-getX() || y>= getFullHeight()-getY()) return (COLORREF)0; + return (COLORREF)(((int*)bits)[x+getX()+(y+getY())*getFullWidth()]); +} + +void *SkinBitmap::getBits() +{ + return bits; +} + +int SkinBitmap::isInvalid() +{ + return last_failed; +} + +void SkinBitmap::setHasAlpha(int ha) +{ + has_alpha=ha; +} + +const wchar_t *SkinBitmap::getBitmapName() +{ + return bitmapname; +} + +void SkinBitmap::AddRef() +{ + references++; +} + +void SkinBitmap::Release() +{ + if (--references == 0) + delete this; +}
\ No newline at end of file diff --git a/Src/tataki/bitmap/win/bitmap.h b/Src/tataki/bitmap/win/bitmap.h new file mode 100644 index 00000000..67640cf8 --- /dev/null +++ b/Src/tataki/bitmap/win/bitmap.h @@ -0,0 +1,113 @@ +//NONPORTABLE +#ifndef _BITMAP_H +#define _BITMAP_H + +#pragma warning( disable: 4251 ) +// http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html + +#include <tataki/export.h> +#include <bfc/platform/platform.h> +class ifc_canvas; // see canvas.h + +//#define NO_MMX + +class api_region; + +// a skinnable bitmap +class TATAKIAPI SkinBitmap +{ +public: + void AddRef(); + void Release(); +#ifndef _NOSTUDIO +#ifdef _WIN32 + SkinBitmap(HINSTANCE hInst, int _id, const wchar_t *colorgroup = NULL); //NONPORTABLE +#endif + SkinBitmap(const wchar_t *elementname, int cached = 1); +#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, bool own=false); // added by benski, use if you have raw image bits + SkinBitmap(ifc_canvas *canvas); + ~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; + wchar_t *bitmapname; + int fromskin; + size_t references; + enum + { + OWNBITS_NOTOURS =0 , + OWNBITS_USEIMGLDR = 1, + OWNBITS_USESTDFREE = 2, + OWNBITS_USECFREE = 3, + OWNBITS_USESYSFREE = 4, + }; +protected: + bool high_quality_resampling; +}; +#ifndef _NOSTUDIO +class HQSkinBitmap : public SkinBitmap +{ +public: + HQSkinBitmap(ARGB32 *bits, int w, int h, bool own=false) : SkinBitmap(bits, w, h, own) + { + high_quality_resampling=true; + } + + HQSkinBitmap(const wchar_t *elementname, int cached = 1) : SkinBitmap(elementname, cached) + { + high_quality_resampling=true; + } +#ifdef _WIN32 + HQSkinBitmap(HINSTANCE hInst, int _id, const wchar_t *colorgroup = NULL) : SkinBitmap(hInst, _id, colorgroup) + { + high_quality_resampling=true; + } +#endif +}; +#endif +#endif diff --git a/Src/tataki/blending/blending.cpp b/Src/tataki/blending/blending.cpp new file mode 100644 index 00000000..24b04e5c --- /dev/null +++ b/Src/tataki/blending/blending.cpp @@ -0,0 +1,54 @@ +#include "blending.h" + +#if !defined(WIN32) && !defined(LINUX) +#error port me! +#endif + +class BlenderInit +{ +public: + BlenderInit() { Blenders::init(); } +}; +static BlenderInit blender_init; + +void Blenders::init() +{ + if (!alphatable[127][127]) + { + int i, j; + for (j = 0;j < 256;j++) + for (i = 0;i < 256;i++) + alphatable[i][j] = (i * (j + 1)) >> 8; +#ifndef NO_MMX + DWORD retval1, retval2; +#ifdef WIN32 + __try { + _asm { + mov eax, 1 // set up CPUID to return processor version and features + // 0 = vendor string, 1 = version info, 2 = cache info + _emit 0x0f // code bytes = 0fh, 0a2h + _emit 0xa2 + mov retval1, eax + mov retval2, edx + } + } __except(EXCEPTION_EXECUTE_HANDLER) { retval1 = retval2 = 0;} +#else + __asm__ volatile ( "movl $1, %%eax\n" + ".byte 15, 162\n" + "movl %%eax, %0\n" + "movl %%edx, %1\n" + : "=m" (retval1), "=m" (retval2) + : // No inputs... + : "%eax", "%edx" ); +#endif + mmx_available = retval1 && (retval2 & 0x800000); +#endif //ndef NO_MMX + + } +} + +#ifndef NO_MMX +int Blenders::mmx_available = 0; +#endif + +unsigned char Blenders::alphatable[256][256] = {0}; diff --git a/Src/tataki/blending/blending.h b/Src/tataki/blending/blending.h new file mode 100644 index 00000000..238ff08f --- /dev/null +++ b/Src/tataki/blending/blending.h @@ -0,0 +1,542 @@ +#ifndef _BLENDING_H_ +#define _BLENDING_H_ + +//#include <bfc/common.h> +#include <bfc/platform/types.h> +#include <tataki/export.h> + +#ifdef _WIN64 +#define NO_MMX +#endif + +class TATAKIAPI Blenders +{ +public: + static void init(); + static unsigned int inline BLEND_ADJ1(unsigned int a, unsigned int b, int alpha); + static unsigned int inline BLEND_ADJ2(unsigned int a, unsigned int b); + static unsigned int inline BLEND_ADJ3(unsigned int a, unsigned int b, int alpha); + static unsigned int inline BLEND_MUL(unsigned int a, int v); + static unsigned int inline BLEND_AVG(unsigned int a, unsigned int b); + static unsigned int inline BLEND4(unsigned int *p1, unsigned int w, int xp, int yp); + +#ifndef NO_MMX + static int inline MMX_AVAILABLE() { return mmx_available; } + static unsigned int inline BLEND_ADJ1_MMX(unsigned int a, unsigned int b, int alpha); + static unsigned int inline BLEND_ADJ2_MMX(unsigned int a, unsigned int b); + static unsigned int inline BLEND_ADJ3_MMX(unsigned int a, unsigned int b, int alpha); + static unsigned int inline BLEND_MUL_MMX(unsigned int a, int v); + static unsigned int inline BLEND_AVG_MMX(unsigned int a, unsigned int b); + static unsigned int inline BLEND4_MMX(unsigned int *p1, unsigned int w, int xp, int yp); + static void inline BLEND_MMX_END() + { +#if defined(WIN32) && !defined(_WIN64) + if (mmx_available) __asm emms; +#endif +#ifdef LINUX +if (mmx_available) __asm__ volatile ( "emms" : : ); +#endif + + } +#endif + +//private: + static uint8_t alphatable[256][256]; +#ifndef NO_MMX + static int mmx_available; +#endif +}; + + +// NON MMX + +// average blend of a and b. +unsigned int inline Blenders::BLEND_AVG(unsigned int a, unsigned int b) +{ + return ((a >> 1)&~((1 << 7) | (1 << 15) | (1 << 23))) + ((b >> 1)&~((1 << 7) | (1 << 15) | (1 << 23))); +} + + +// multiplies 32 bit color A by scalar V (0-255) +unsigned int inline Blenders::BLEND_MUL(unsigned int a, int v) +{ + register int t; + t = Blenders::alphatable[a & 0xFF][v]; + t |= Blenders::alphatable[(a & 0xFF00) >> 8][v] << 8; + t |= Blenders::alphatable[(a & 0xFF0000) >> 16][v] << 16; + t |= Blenders::alphatable[(a & 0xFF000000) >> 24][v] << 24; + return t; +} + + +// V is scalar (0-255), (1.0-V)*b + V*a +unsigned int inline Blenders::BLEND_ADJ1(unsigned int a, unsigned int b, int v) +{ + register int t; + t = Blenders::alphatable[b & 0xFF][0xFF - v] + Blenders::alphatable[a & 0xFF][v]; + t |= (Blenders::alphatable[(b & 0xFF00) >> 8][0xFF - v] + Blenders::alphatable[(a & 0xFF00) >> 8][v]) << 8; + t |= (Blenders::alphatable[(b & 0xFF0000) >> 16][0xFF - v] + Blenders::alphatable[(a & 0xFF0000) >> 16][v]) << 16; + t |= (Blenders::alphatable[(b & 0xFF000000) >> 24][0xFF - v] + Blenders::alphatable[(a & 0xFF000000) >> 24][v]) << 24; + return t; +} + +// returns a*(1.0-Alpha(b)) + b +unsigned int inline Blenders::BLEND_ADJ2(unsigned int a, unsigned int b) +{ + register int t, z; + int v = 0xff - ((b >> 24) & 0xff); + t = Blenders::alphatable[a & 0xFF][v] + (b & 0xFF); + if (t > 0xFF) t = 0xff; + z = (Blenders::alphatable[(a & 0xFF00) >> 8][v] << 8) + (b & 0xFF00); + if (z > 0xFF00) z = 0xff00; + t |= z; + z = (Blenders::alphatable[(a & 0xFF0000) >> 16][v] << 16) + ((b & 0xFF0000)); + if (z > 0xFF0000) z = 0xff0000; + t |= z; + z = (Blenders::alphatable[(a & 0xFF000000) >> 24][v]) + ((b & 0xFF000000) >> 24); + if (z > 0xFF) z = 0xff; + return t | (z << 24); +} + +// returns a*(1-Alpha(b)*W) + b*W, clamped (W is scalar 0-0xff). +unsigned int inline Blenders::BLEND_ADJ3(unsigned int a, unsigned int b, int w) +{ + register int t, z; + int v = 0xff - Blenders::alphatable[(b >> 24) & 0xff][w]; + + t = Blenders::alphatable[a & 0xFF][v] + Blenders::alphatable[b & 0xFF][w]; + if (t > 0xFF) t = 0xFF; + z = Blenders::alphatable[(a & 0xFF00) >> 8][v] + Blenders::alphatable[(b & 0xFF00) >> 8][w]; + if (z > 0xFF) z = 0xFF; + t |= z << 8; + z = Blenders::alphatable[(a & 0xFF0000) >> 16][v] + Blenders::alphatable[(b & 0xFF0000) >> 16][w]; + if (z > 0xFF) z = 0xFF; + t |= z << 16; + z = Blenders::alphatable[(a & 0xFF000000) >> 24][v] + Blenders::alphatable[(b & 0xFF000000) >> 24][w]; + if (z > 0xFF) z = 0xFF; + return t | (z << 24); +} + +unsigned int __inline Blenders::BLEND4(unsigned int *p1, unsigned int w, int xp, int yp) +{ + register int t; + uint8_t a1, a2, a3, a4; + xp = (xp >> 8) & 0xff; + yp = (yp >> 8) & 0xff; + a1 = alphatable[255 - xp][255 - yp]; + a2 = alphatable[xp][255 - yp]; + a3 = alphatable[255 - xp][yp]; + a4 = alphatable[xp][yp]; + t = alphatable[p1[0] & 0xff][a1] + alphatable[p1[1] & 0xff][a2] + alphatable[p1[w] & 0xff][a3] + alphatable[p1[w + 1] & 0xff][a4]; + t |= (alphatable[(p1[0] >> 8) & 0xff][a1] + alphatable[(p1[1] >> 8) & 0xff][a2] + alphatable[(p1[w] >> 8) & 0xff][a3] + alphatable[(p1[w + 1] >> 8) & 0xff][a4]) << 8; + t |= (alphatable[(p1[0] >> 16) & 0xff][a1] + alphatable[(p1[1] >> 16) & 0xff][a2] + alphatable[(p1[w] >> 16) & 0xff][a3] + alphatable[(p1[w + 1] >> 16) & 0xff][a4]) << 16; + t |= (alphatable[(p1[0] >> 24) & 0xff][a1] + alphatable[(p1[1] >> 24) & 0xff][a2] + alphatable[(p1[w] >> 24) & 0xff][a3] + alphatable[(p1[w + 1] >> 24) & 0xff][a4]) << 24; + return t; +} + + + + +#ifndef NO_MMX + + +#ifdef WIN32 +#pragma warning( push, 1 ) +#pragma warning(disable: 4799) +#endif + +#ifdef WIN32 +#define MMX_CONST const +#else +#define MMX_CONST +#endif + +static unsigned int MMX_CONST Blenders__mmx_revn2[2] = {0x01000100, 0x01000100}; +static unsigned int MMX_CONST Blenders__mmx_zero[2]; +static unsigned int MMX_CONST Blenders__mmx_one[2] = {1, 0}; + +#undef MMX_CONST + +/// MMX + +// average blend of a and b. +unsigned int inline Blenders::BLEND_AVG_MMX(unsigned int a, unsigned int b) +{ + return ((a >> 1)&~((1 << 7) | (1 << 15) | (1 << 23))) + ((b >> 1)&~((1 << 7) | (1 << 15) | (1 << 23))); +} + +// multiplies 32 bit color A by scalar V (0-255) +unsigned int inline Blenders::BLEND_MUL_MMX(unsigned int a, int v) +{ +#ifdef WIN32 + __asm + { + movd mm3, [v] // VVVVVVVV + + movd mm0, [a] + packuswb mm3, mm3 // 0000HHVV + + punpcklbw mm0, [Blenders__mmx_zero] + punpcklwd mm3, mm3 // HHVVHHVV + + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + + pmullw mm0, mm3 + + psrlw mm0, 8 + + packuswb mm0, mm0 + + movd eax, mm0 + } +#else + __asm__ volatile ( + "movd %0, %%mm3\n" + "movd %1, %%mm0\n" + "packuswb %%mm3, %%mm3\n" + "punpcklbw (Blenders__mmx_zero), %%mm0\n" + "punpcklwd %%mm3, %%mm3\n" + "punpckldq %%mm3, %%mm3\n" + "pmullw %%mm3, %%mm0\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, %%eax\n" + : + : "m" (v), "m" (a) + : "%mm0", "%mm3" ); +#endif +} + + +// V is scalar (0-255), (1.0-V)*b + V*a +unsigned int inline Blenders::BLEND_ADJ1_MMX(unsigned int a, unsigned int b, int v) +{ +#ifdef WIN32 + __asm + { + movd mm3, [v] // VVVVVVVV + + movd mm0, [a] + packuswb mm3, mm3 // 0000HHVV + + movd mm1, [b] + paddusw mm3, [Blenders__mmx_one] + + movq mm4, [Blenders__mmx_revn2] + punpcklwd mm3, mm3 // HHVVHHVV + + punpcklbw mm0, [Blenders__mmx_zero] + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + + punpcklbw mm1, [Blenders__mmx_zero] + psubw mm4, mm3 + + pmullw mm0, mm3 + pmullw mm1, mm4 + + paddw mm0, mm1 + + psrlw mm0, 8 + + packuswb mm0, mm0 + + movd eax, mm0 + } +#else + __asm__ volatile ( + "movd %0, %%mm3\n" + "movd %1, %%mm0\n" + "packuswb %%mm3, %%mm3\n" + "movd %2, %%mm1\n" + "paddusw (Blenders__mmx_one), %%mm3\n" + "movq (Blenders__mmx_revn2), %%mm4\n" + "punpcklwd %%mm3, %%mm3\n" + "punpcklbw (Blenders__mmx_zero), %%mm0\n" + "punpckldq %%mm3, %%mm3\n" + "punpcklbw (Blenders__mmx_zero), %%mm1\n" + "psubw %%mm3, %%mm4\n" + "pmullw %%mm3, %%mm0\n" + "pmullw %%mm4, %%mm1\n" + "paddw %%mm1, %%mm0\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, %%eax\n" + : + : "m" (v), "m" (a), "m" (b) + : "%mm0", "%mm1", "%mm3", "%mm4" ); +#endif +} + +// returns a*(1.0-Alpha(b)) + b +unsigned int inline Blenders::BLEND_ADJ2_MMX(unsigned int a, unsigned int b) +{ +#ifdef WIN32 + __asm + { + movd mm3, [b] // VVVVVVVV + movq mm4, [Blenders__mmx_revn2] + + movd mm0, [a] + psrld mm3, 24 + + movd mm1, [b] + paddusw mm3, [Blenders__mmx_one] + + punpcklwd mm3, mm3 // HHVVHHVV + punpcklbw mm0, [Blenders__mmx_zero] + + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + punpcklbw mm1, [Blenders__mmx_zero] + + psubw mm4, mm3 + + pmullw mm0, mm4 + // stall + + // stall + + // stall + + psrlw mm0, 8 + // stall + + paddw mm0, mm1 + // stall + + packuswb mm0, mm0 + // stall + + movd eax, mm0 + } +#else + __asm__ volatile ( + "movd %1, %%mm3\n" + "movq (Blenders__mmx_revn2), %%mm4\n" + "movd %0, %%mm0\n" + "psrld $24, %%mm3\n" + "movd %1, %%mm1\n" + "paddusw (Blenders__mmx_one), %%mm3\n" + "punpcklwd %%mm3, %%mm3\n" + "punpcklbw (Blenders__mmx_zero), %%mm0\n" + "punpckldq %%mm3, %%mm3\n" + "punpcklbw (Blenders__mmx_zero), %%mm1\n" + "psubw %%mm3, %%mm4\n" + "pmullw %%mm4, %%mm0\n" + "psrlw $8, %%mm0\n" + "paddw %%mm1, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, %%eax\n" + : + : "m" (a), "m" (b) + : "%esi", "%mm0", "%mm1", "%mm3", "%mm4" ); +#endif +} + +// returns a*(1-Alpha(b)*W) + b*W, clamped (W is scalar 0-0xff). +unsigned int inline Blenders::BLEND_ADJ3_MMX(unsigned int a, unsigned int b, int w) +{ +#ifdef WIN32 + __asm + { + movd mm3, [b] // VVVVVVVV + movd mm5, [w] + + movd mm0, [a] + psrld mm3, 24 + + movd mm1, [b] + paddusw mm3, [Blenders__mmx_one] + + movq mm4, [Blenders__mmx_revn2] + pmullw mm3, mm5 + + packuswb mm5, mm5 + punpcklbw mm0, [Blenders__mmx_zero] + + punpcklwd mm5, mm5 + punpcklbw mm1, [Blenders__mmx_zero] + + psrlw mm3, 8 + punpckldq mm5, mm5 + + paddusw mm3, [Blenders__mmx_one] + + punpcklwd mm3, mm3 // HHVVHHVV + + punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV + + + psubw mm4, mm3 + + pmullw mm0, mm4 + pmullw mm1, mm5 + + paddusw mm0, mm1 + + psrlw mm0, 8 + + packuswb mm0, mm0 + + movd eax, mm0 + } +#else + __asm__ volatile ( + "movd %2, %%mm3\n" + "movd %0, %%mm5\n" + "movd %1, %%mm0\n" + "psrld $24, %%mm3\n" + "movd %2, %%mm1\n" + "paddusw (Blenders__mmx_one), %%mm3\n" + "movq (Blenders__mmx_revn2), %%mm4\n" + "pmullw %%mm5, %%mm3\n" + "packuswb %%mm5, %%mm5 \n" + "punpcklbw (Blenders__mmx_zero), %%mm0\n" + "punpcklwd %%mm5, %%mm5\n" + "punpcklbw (Blenders__mmx_zero), %%mm1\n" + "psrlw $8, %%mm3\n" + "punpckldq %%mm5, %%mm5\n" + "paddusw (Blenders__mmx_one), %%mm3\n" + "punpcklwd %%mm3, %%mm3\n" + "punpckldq %%mm3, %%mm3\n" + "psubw %%mm3, %%mm4\n" + "pmullw %%mm4, %%mm0\n" + "pmullw %%mm5, %%mm1\n" + "paddusw %%mm1, %%mm0\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, %%eax\n" + + : + : "m" (w), "m" (a), "m" (b) + : "%mm0", "%mm1", "%mm4", "%mm3", "%mm5" ); +#endif +} + +// does bilinear filtering. p1 is upper left pixel, w is width of framebuffer +// xp and yp's low 16 bits are used for the subpixel positioning. +unsigned int inline Blenders::BLEND4_MMX(unsigned int *p1, unsigned int w, int xp, int yp) +{ +#ifdef WIN32 + __asm + { + movd mm6, xp + mov eax, p1 + + movd mm7, yp + mov esi, w + + movq mm4, Blenders__mmx_revn2 + psrlw mm6, 8 + + movq mm5, Blenders__mmx_revn2 + psrlw mm7, 8 + + movd mm0, [eax] + punpcklwd mm6, mm6 + + movd mm1, [eax + 4] + punpcklwd mm7, mm7 + + movd mm2, [eax + esi*4] + punpckldq mm6, mm6 + + movd mm3, [eax + esi*4 + 4] + punpckldq mm7, mm7 + + punpcklbw mm0, [Blenders__mmx_zero] + psubw mm4, mm6 + + punpcklbw mm1, [Blenders__mmx_zero] + pmullw mm0, mm4 + + punpcklbw mm2, [Blenders__mmx_zero] + pmullw mm1, mm6 + + punpcklbw mm3, [Blenders__mmx_zero] + psubw mm5, mm7 + + pmullw mm2, mm4 + pmullw mm3, mm6 + + paddw mm0, mm1 + // stall (mm0) + + psrlw mm0, 8 + // stall (waiting for mm3/mm2) + + paddw mm2, mm3 + pmullw mm0, mm5 + + psrlw mm2, 8 + // stall (mm2) + + pmullw mm2, mm7 + // stall + + // stall (mm2) + + paddw mm0, mm2 + // stall + + psrlw mm0, 8 + // stall + + packuswb mm0, mm0 + // stall + + movd eax, mm0 + } +#else + __asm__ volatile ( + "movd %2, %%mm6\n" + "mov %0, %%eax\n" + "movd %3, %%mm7\n" + "mov %1, %%esi\n" + "movq (Blenders__mmx_revn2), %%mm4\n" + "psrlw $8, %%mm6\n" + "movq (Blenders__mmx_revn2), %%mm5\n" + "psrlw $8, %%mm7\n" + "movd (%%eax), %%mm0\n" + "punpcklwd %%mm6,%%mm6\n" + "movd 4(%%eax), %%mm1\n" + "punpcklwd %%mm7,%%mm7\n" + "movd (%%eax,%%esi,4), %%mm2\n" + "punpckldq %%mm6,%%mm6\n" + "movd 4(%%eax,%%esi,4), %%mm3\n" + "punpckldq %%mm7,%%mm7\n" + "punpcklbw (Blenders__mmx_zero), %%mm0\n" + "psubw %%mm6, %%mm4\n" + "punpcklbw (Blenders__mmx_zero), %%mm1\n" + "pmullw %%mm4, %%mm0\n" + "punpcklbw (Blenders__mmx_zero), %%mm2\n" + "pmullw %%mm6, %%mm1\n" + "punpcklbw (Blenders__mmx_zero), %%mm3\n" + "psubw %%mm7, %%mm5\n" + "pmullw %%mm4, %%mm2\n" + "pmullw %%mm6, %%mm3\n" + "paddw %%mm1, %%mm0\n" + "psrlw $8, %%mm0\n" + "paddw %%mm3, %%mm2\n" + "pmullw %%mm5, %%mm0\n" + "psrlw $8, %%mm2\n" + "pmullw %%mm7, %%mm2\n" + "paddw %%mm2, %%mm0\n" + "psrlw $8, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "movd %%mm0, %%eax\n" + + : + : "m" (p1), "m" (w), "m" (xp), "m" (yp) + : "%mm0", "%mm1", "%mm4", "%mm3", "%mm5" ); + +#endif +} + +#ifdef WIN32 +#pragma warning( pop ) +#endif + +#endif // ndef NO_MMX + + +#endif diff --git a/Src/tataki/canvas/PaintCanvas.h b/Src/tataki/canvas/PaintCanvas.h new file mode 100644 index 00000000..f32e74e4 --- /dev/null +++ b/Src/tataki/canvas/PaintCanvas.h @@ -0,0 +1,3 @@ +#ifdef __APPLE__ +#include "mac/PaintCanvas.h" +#endif
\ No newline at end of file diff --git a/Src/tataki/canvas/bltcanvas.h b/Src/tataki/canvas/bltcanvas.h new file mode 100644 index 00000000..6ffa07a5 --- /dev/null +++ b/Src/tataki/canvas/bltcanvas.h @@ -0,0 +1,5 @@ +#ifdef _WIN32 +#include "win/bltcanvas.h" +#elif defined(__APPLE__) +#include "mac/bltcanvas.h" +#endif diff --git a/Src/tataki/canvas/canvas.h b/Src/tataki/canvas/canvas.h new file mode 100644 index 00000000..b645a654 --- /dev/null +++ b/Src/tataki/canvas/canvas.h @@ -0,0 +1,5 @@ +#ifdef _WIN32 +#include "win/canvas.h" +#elif defined(__APPLE__) +#include "mac/canvas.h" +#endif
\ No newline at end of file diff --git a/Src/tataki/canvas/ifc_canvas.cpp b/Src/tataki/canvas/ifc_canvas.cpp new file mode 100644 index 00000000..b209c9de --- /dev/null +++ b/Src/tataki/canvas/ifc_canvas.cpp @@ -0,0 +1 @@ +#include "ifc_canvas.h"
\ No newline at end of file diff --git a/Src/tataki/canvas/ifc_canvas.h b/Src/tataki/canvas/ifc_canvas.h new file mode 100644 index 00000000..6c7796cf --- /dev/null +++ b/Src/tataki/canvas/ifc_canvas.h @@ -0,0 +1,165 @@ +#ifndef NULLSOFT_TATAKI_IFC_CANVAS_H +#define NULLSOFT_TATAKI_IFC_CANVAS_H + +#include <bfc/dispatch.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/wasabi_std.h> // for WASABI_DEFAULT_FONTNAMEW + +namespace Wasabi +{ + // benski> move this to std_font later +struct FontInfo +{ + FontInfo() + { + // defaults + face = WASABI_DEFAULT_FONTNAMEW; + pointSize = 12; + bold = 0; + opaque = false; + underline = false; + italic = false; + alignFlags = STDFONT_LEFT; + antialias = 1; + bgColor = RGBA(255, 255, 255, 255); + color = RGBA(0, 0, 0, 0); + } + + const wchar_t *face; + unsigned int pointSize; + int bold; // bold level + bool opaque; + bool underline; + bool italic; + int alignFlags; + int antialias; // anti-alias level + ARGB32 color; + ARGB32 bgColor; +}; +} + +class ifc_window; +// abstract base class: safe to use in API +class NOVTABLE ifc_canvas : public Dispatchable +{ +protected: + ifc_canvas() + {} // protect constructor + ~ifc_canvas() + {} + +public: + DISPATCH_CODES + { + GETHDC = 100, + GETROOTWND = 200, + GETBITS = 300, + GETOFFSETS = 400, + ISFIXEDCOORDS = 500, + GETDIM = 600, + GETTEXTFONT = 700, + GETTEXTSIZE = 710, + GETTEXTBOLD = 720, + GETTEXTOPAQUE = 730, + GETTEXTALIGN = 740, + GETTEXTCOLOR = 750, + GETTEXTBKCOLOR = 760, + GETTEXTAA = 770, + GETTEXTUNDERLINE = 780, + GETTEXTITALIC = 790, + GETCLIPBOX = 800, + }; +public: + HDC getHDC(); + ifc_window *getRootWnd(); + void *getBits(); + void getOffsets(int *x, int *y); + bool isFixedCoords(); //FG> allows onPaint to handle double buffers as well as normal DCs + bool getDim(int *w, int *h = NULL, int *p = NULL); // w & h in pixels, pitch in bytes. 0 on success. + int getClipBox(RECT *r); // returns 0 if no clipping region + const wchar_t *getTextFont(); + int getTextSize(); + int getTextBold(); + int getTextAntialias(); + int getTextOpaque(); + int getTextUnderline(); + int getTextItalic(); + int getTextAlign(); + ARGB32 getTextColor(); + ARGB32 getTextBkColor(); +}; + + +inline HDC ifc_canvas::getHDC() +{ + return _call(ifc_canvas::GETHDC, (HDC)0); +} +inline ifc_window *ifc_canvas::getRootWnd() +{ + return _call(ifc_canvas::GETROOTWND, (ifc_window*)0); +} +inline void *ifc_canvas::getBits() +{ + return _call(ifc_canvas::GETBITS, (void *)0); +} +inline void ifc_canvas::getOffsets(int *x, int *y) +{ + _voidcall(ifc_canvas::GETOFFSETS, x, y); +} +inline bool ifc_canvas::isFixedCoords() +{ //FG> allows onPaint to handle double buffers as well as normal DCs + return _call(ifc_canvas::ISFIXEDCOORDS, false); +} +inline bool ifc_canvas::getDim(int *w, int *h, int *p) +{ // w & h in pixels, pitch in bytes. 0 on success. + return _call(ifc_canvas::GETDIM, false, w, h, p); +} +inline int ifc_canvas::getClipBox(RECT *r) +{ // returns 0 if no clipping region + return _call(ifc_canvas::GETCLIPBOX, 0, r); +} + +inline const wchar_t *ifc_canvas::getTextFont() +{ + return _call(ifc_canvas::GETTEXTFONT, L""); +} +inline int ifc_canvas::getTextSize() +{ + return _call(ifc_canvas::GETTEXTSIZE, -1); +} +inline int ifc_canvas::getTextBold() +{ + return _call(ifc_canvas::GETTEXTBOLD, 0); +} +inline int ifc_canvas::getTextAntialias() +{ + return _call(ifc_canvas::GETTEXTAA, 0); +} +inline int ifc_canvas::getTextOpaque() +{ + return _call(ifc_canvas::GETTEXTOPAQUE, 0); +} +inline int ifc_canvas::getTextUnderline() +{ + return _call(ifc_canvas::GETTEXTUNDERLINE, 0); +} +inline int ifc_canvas::getTextItalic() +{ + return _call(ifc_canvas::GETTEXTITALIC, 0); +} +inline int ifc_canvas::getTextAlign() +{ + return _call(ifc_canvas::GETTEXTALIGN, -1); +} +inline ARGB32 ifc_canvas::getTextColor() +{ + return _call(ifc_canvas::GETTEXTCOLOR, RGB(0, 0, 0)); +} +inline ARGB32 ifc_canvas::getTextBkColor() +{ + return _call(ifc_canvas::GETTEXTBKCOLOR, RGB(255, 255, 255)); +} + +typedef ifc_canvas api_canvas; +#endif diff --git a/Src/tataki/canvas/mac/PaintCanvas.cpp b/Src/tataki/canvas/mac/PaintCanvas.cpp new file mode 100644 index 00000000..6cfeb126 --- /dev/null +++ b/Src/tataki/canvas/mac/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/tataki/canvas/mac/PaintCanvas.h b/Src/tataki/canvas/mac/PaintCanvas.h new file mode 100644 index 00000000..58379508 --- /dev/null +++ b/Src/tataki/canvas/mac/PaintCanvas.h @@ -0,0 +1,46 @@ +#ifndef NULLSOFT_WASABI_OSX_PAINTCANVAS_H +#define NULLSOFT_WASABI_OSX_PAINTCANVAS_H + +#include <tataki/export.h> +#include <tataki/canvas/canvas.h> +#include <api/wnd/basewnd.h> + +class TATAKIAPI PaintCanvas : public Canvas +{ +public: + PaintCanvas(); + ~PaintCanvas(); + bool beginPaint(BaseWnd *wnd); +protected: + CGrafPtr qdcontext; +}; + +class TATAKIAPI PaintBltCanvas : public PaintCanvas +{ +public: + bool beginPaintNC(BaseWnd *wnd) + { + return beginPaint(wnd); + } +}; +#warning port PaintBltCanvas +class TATAKIAPI WndCanvas : public Canvas +{ +public: + WndCanvas(); + virtual ~WndCanvas(); + + // address client area + int attachToClient(BaseWnd *basewnd); + +private: + CGrafPtr qdcontext; +}; + +class TATAKIAPI TextInfoCanvas : public Canvas +{ +public: + TextInfoCanvas(BaseWnd *baseWnd); + virtual ~TextInfoCanvas(); +}; +#endif
\ No newline at end of file diff --git a/Src/tataki/canvas/mac/bltcanvas.h b/Src/tataki/canvas/mac/bltcanvas.h new file mode 100644 index 00000000..e1005dc8 --- /dev/null +++ b/Src/tataki/canvas/mac/bltcanvas.h @@ -0,0 +1,27 @@ +#ifndef _BLTCANVAS_H +#define _BLTCANVAS_H + +#include <tataki/export.h> +#include "canvas.h" + +class TATAKIAPI 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(api_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(api_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/tataki/canvas/mac/canvas.h b/Src/tataki/canvas/mac/canvas.h new file mode 100644 index 00000000..5258af4e --- /dev/null +++ b/Src/tataki/canvas/mac/canvas.h @@ -0,0 +1,70 @@ +#ifndef NULLSOFT_WASABI_CANVAS_H +#define NULLSOFT_WASABI_CANVAS_H + +#include <tataki/export.h> +#include <Carbon/Carbon.h> +#include <tataki/canvas/api_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 TATAKIAPI Canvas : public api_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 TATAKIAPI BaseCloneCanvas : public Canvas +{ +public: + BaseCloneCanvas(api_canvas *cloner=NULL); + virtual ~BaseCloneCanvas(); + + int clone(api_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/tataki/canvas/mac/osx_canvas_layer.cpp b/Src/tataki/canvas/mac/osx_canvas_layer.cpp new file mode 100644 index 00000000..c6f80347 --- /dev/null +++ b/Src/tataki/canvas/mac/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(api_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(api_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/tataki/canvas/mac/osx_canvas_quartz.cpp b/Src/tataki/canvas/mac/osx_canvas_quartz.cpp new file mode 100644 index 00000000..dcbae59f --- /dev/null +++ b/Src/tataki/canvas/mac/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(api_canvas *cloner) +{ + if (cloner != NULL) clone(cloner); +} + +int BaseCloneCanvas::clone(api_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/tataki/canvas/win/BltCanvas.cpp b/Src/tataki/canvas/win/BltCanvas.cpp new file mode 100644 index 00000000..5b9a94bc --- /dev/null +++ b/Src/tataki/canvas/win/BltCanvas.cpp @@ -0,0 +1,295 @@ +#include "bltcanvas.h" +#include <tataki/bitmap/bitmap.h> + +BltCanvas::~BltCanvas() +{ + if (hdc == NULL) return ; + + // kill the bitmap and its DC + SelectObject(hdc, prevbmp); + if (ourbmp) + { + //GdiFlush(); + DeleteObject(hbmp); + } + DeleteDC(hdc); + hdc = NULL; + + if (skinbmps) + { + for (int i=0;i<skinbmps->getNumItems();i++) + skinbmps->enumItem(i)->Release(); + + delete skinbmps; + } + if (envelope) + envelope->Release(); +} + +BltCanvas::BltCanvas(HBITMAP bmp) +{ + prevbmp = NULL; + bits = NULL; + fcoord = TRUE; + ourbmp = FALSE; + skinbmps = NULL; + envelope = NULL; + + hbmp = bmp; + ASSERT(hbmp != NULL); + + // create tha DC + hdc = CreateCompatibleDC(NULL); + prevbmp = (HBITMAP)SelectObject(hdc, hbmp); +} + +BltCanvas::BltCanvas() +{ + hbmp = NULL; + prevbmp = NULL; + bits = NULL; + fcoord = TRUE; + ourbmp = FALSE; + bpp = 32; // TODO: benski> pass as parameter? + skinbmps = NULL; + envelope = NULL; + hdc = CreateCompatibleDC(NULL); +} + +BltCanvas::BltCanvas(int w, int h, HWND wnd, int nb_bpp/*, unsigned char *pal, int palsize*/) +{ + hbmp = NULL; + prevbmp = NULL; + bits = NULL; + fcoord = TRUE; + ourbmp = FALSE; + bpp = nb_bpp; + skinbmps = NULL; + envelope = NULL; + hdc = CreateCompatibleDC(NULL); + AllocBitmap(w,h,nb_bpp); + + if (hbmp) + { + // create tha DC + + if (!hdc) { +// int x = GetLastError(); + } + prevbmp = (HBITMAP)SelectObject(hdc, hbmp); + } +} + +void BltCanvas::AllocBitmap(int w, int h, int nb_bpp) +{ + ASSERT(!hbmp); + ASSERT(w != 0 && h != 0); + if (w == 0) w = 1; + if (h == 0) h = 1; + + BITMAPINFO bmi; + MEMZERO(&bmi, sizeof(BITMAPINFO)); + //bmi.bmiHeader.biClrUsed = 0; // we memzero above, no need + //bmi.bmiHeader.biClrImportant = 0; // we memzero above, no need + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = ABS(w); + bmi.bmiHeader.biHeight = -ABS(h); + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = nb_bpp; + bmi.bmiHeader.biCompression = BI_RGB; + //bmi.bmiHeader.biSizeImage = 0; // we memzero above, no need + //bmi.bmiHeader.biXPelsPerMeter = 0; // we memzero above, no need + //bmi.bmiHeader.biYPelsPerMeter = 0; // we memzero above, no need + //GdiFlush(); + hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0); + + if (hbmp == NULL) + { + return ; + } + + ourbmp=TRUE; + GetObject(hbmp, sizeof(BITMAP), &bm); + width = bm.bmWidth; + height = ABS(bm.bmHeight); + pitch = bm.bmWidthBytes; +} + +void *BltCanvas::getBits() +{ + return bits; +} + +HBITMAP BltCanvas::getBitmap() +{ + return hbmp; +} + +SkinBitmap *BltCanvas::getSkinBitmap() +{ + // make a SkinBitmap envelope + if (!envelope) + envelope = new SkinBitmap(getBitmap(), getHDC(), 1, getBits()); + + // do not delete envelope, it's deleted in destructor + return envelope; +} + +SkinBitmap *BltCanvas::makeSkinBitmap() +{ + // make a clone of the bitmap - JF> what was that crap about envelopes? + SkinBitmap *clone = new SkinBitmap(getBitmap(), getHDC(), 1); + + if (!skinbmps) + skinbmps = new PtrList<SkinBitmap>; + skinbmps->addItem(clone); + + return clone; +} + +void BltCanvas::disposeSkinBitmap(SkinBitmap *b) +{ + if (skinbmps->haveItem(b)) + { + skinbmps->removeItem(b); + b->Release(); + } + else + { + DebugString("disposeSkinBitmap called on unknown pointer, you should call it from the object used to makeSkinBitmap()\n"); + } +} + +void BltCanvas::fillBits(COLORREF color) +{ + if (bpp == 32) + { // clear out the bits + DWORD *dwbits = (DWORD *)bits; + MEMFILL<DWORD>(dwbits, color, bm.bmWidth * bm.bmHeight); + } +} + +void BltCanvas::vflip(int vert_cells) +{ + ASSERT(bits != NULL); + // BITMAP bm; + // int r = GetObject(hbmp, sizeof(BITMAP), &bm); + // if (r == 0) return; + int w = bm.bmWidth, h = bm.bmHeight; + int bytes = 4 * w; + __int8 *tmpbuf = (__int8 *)MALLOC(bytes); + if (tmpbuf) + { + int cell_h = h / vert_cells; + for (int j = 0; j < vert_cells; j++) + for (int i = 0; i < cell_h / 2; i++) + { + char *p1, *p2; + p1 = (__int8 *)bits + bytes * i + (j * cell_h * bytes); + p2 = (__int8 *)bits + bytes * ((cell_h - 1) - i) + (j * cell_h * bytes); + if (p1 == p2) continue; + MEMCPY(tmpbuf, p1, bytes); + MEMCPY(p1, p2, bytes); + MEMCPY(p2, tmpbuf, bytes); + } + FREE(tmpbuf); + } +} + +void BltCanvas::hflip(int hor_cells) +{ + ASSERT(bits != NULL); + // todo: optimize + int w = bm.bmWidth, h = bm.bmHeight; + for (int i = 0;i < hor_cells;i++) + for (int x = 0;x < w / 2 / hor_cells;x++) + for (int y = 0;y < h;y++) + { + int *p = ((int *)bits) + x + y * w + (i * w / hor_cells); + int *d = ((int *)bits) + ((w / hor_cells) - x) + y * w + (i * w / hor_cells) - 1; + int t = *p; + *p = *d; + *d = t; + } +} + +void BltCanvas::maskColor(COLORREF from, COLORREF to) +{ + int n = bm.bmWidth * bm.bmHeight; + //GdiFlush(); + DWORD *b = (DWORD *)getBits(); + from &= 0xffffff; + while (n--) + { + if ((*b & 0xffffff) == from) + { + *b = to; + } + else *b |= 0xff000000; // force all other pixels non masked + b++; + } +} + +void BltCanvas::makeAlpha(int newalpha) +{ + int w, h; + getDim(&w, &h, NULL); + premultiply((ARGB32 *)getBits(), w*h, newalpha); +} + +#if 0 +void BltCanvas::premultiply(ARGB32 *m_pBits, int nwords, int newalpha) +{ + if (newalpha == -1) + { + for (; nwords > 0; nwords--, m_pBits++) + { + unsigned char *pixel = (unsigned char *)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 + } + } + else + { + for (; nwords > 0; nwords--, m_pBits++) + { + unsigned char *pixel = (unsigned char *)m_pBits; + pixel[0] = (pixel[0] * newalpha) >> 8; // blue + pixel[1] = (pixel[1] * newalpha) >> 8; // green + pixel[2] = (pixel[2] * newalpha) >> 8; // red + pixel[3] = (pixel[3] * newalpha) >> 8; // alpha + } + } +} +#endif + +// benski> this may not be completely safe. it's meant for skinbitmap::blittorect +// it doesn't take into account skin bitmaps, enveloped bitmaps, or any other things like that +void BltCanvas::DestructiveResize(int w, int h, int nb_bpp) +{ + if (hdc != NULL) + { + SelectObject(hdc, prevbmp); + prevbmp=0; + } + + if (ourbmp && hbmp) + { + DeleteObject(hbmp); + hbmp=NULL; + ourbmp=FALSE; + } + + // create tha DC + if (hdc == NULL) + hdc = CreateCompatibleDC(NULL); + + AllocBitmap(w,h,nb_bpp); + + prevbmp = (HBITMAP)SelectObject(hdc, hbmp); + if (envelope) envelope->Release(); + envelope=0; +} diff --git a/Src/tataki/canvas/win/bltcanvas.h b/Src/tataki/canvas/win/bltcanvas.h new file mode 100644 index 00000000..250e8ba3 --- /dev/null +++ b/Src/tataki/canvas/win/bltcanvas.h @@ -0,0 +1,41 @@ +#ifndef _BLTCANVAS_H +#define _BLTCANVAS_H + +#include "canvas.h" +#include <tataki/export.h> +#include <bfc/ptrlist.h> +class TATAKIAPI BltCanvas : public Canvas +{ +public: + BltCanvas(); + BltCanvas(int w, int h, HWND wnd=NULL, int nb_bpp=32/*, unsigned __int8 *pal=NULL,int palsize=0*/); + BltCanvas(HBITMAP bmp); + virtual ~BltCanvas(); + void *getBits(); + HBITMAP getBitmap(); + SkinBitmap *makeSkinBitmap(); // this one makes a new, with own bits + SkinBitmap *getSkinBitmap(); // this one gives a skinbitmap envoloppe of this bltcanvas + void disposeSkinBitmap(SkinBitmap *b); // call only after makeSkinBitmap + + void fillBits(COLORREF color); + + void vflip(int vert_cells=1); + void hflip(int hor_cells=1); + void maskColor(COLORREF from, COLORREF to); + void makeAlpha(int newalpha=-1); // -1 = premultiply using current alpha + + void DestructiveResize(int w, int h, int nb_bpp = 32); // resizes the bitmap, destroying the contents +private: // NONPORTABLE + + void AllocBitmap(int w, int h, int nb_bpp); + HBITMAP hbmp, prevbmp; + PtrList<SkinBitmap> *skinbmps; + SkinBitmap *envelope; + BITMAP bm; + bool ourbmp; + int bpp; + + //void premultiply(ARGB32 *m_pBits, int nwords, int newalpha=-1); +}; + +#endif diff --git a/Src/tataki/canvas/win/canvas.h b/Src/tataki/canvas/win/canvas.h new file mode 100644 index 00000000..179e3498 --- /dev/null +++ b/Src/tataki/canvas/win/canvas.h @@ -0,0 +1,368 @@ +//NONPORTABLE: the interface is portable, but the implementation sure isn't +#ifndef _CANVAS_H +#define _CANVAS_H + +#if defined _WIN64 || defined _WIN32 +#include <ddraw.h> +#endif + +//#include <bfc/common.h> +#include <tataki/export.h> + +class Canvas; +class MemCanvasBmp; +class BaseWnd; +class ifc_window; +class api_region; +class SkinBitmap; + +#include <bfc/stack.h> +#include <api/service/svcs/svc_font.h> // for STDFONT_* stuff. should make a std_font thingy later +#include <bfc/dispatch.h> + +enum { +#ifdef WIN32 + PENSTYLE_SOLID = PS_SOLID, + PENSTYLE_DASH = PS_DASH, + PENSTYLE_DOT = PS_DOT, +#else + PENSTYLE_SOLID = LineSolid, + PENSTYLE_DASH = LineDoubleDash, + PENSTYLE_DOT = LineDoubleDash, +#endif +}; + +#include <tataki/canvas/ifc_canvas.h> +class ifc_canvas; +class RegionI; +typedef struct +{ + int style; + int width; + COLORREF color; + HPEN hpen; +} +penstruct; + +class TATAKIAPI NOVTABLE Canvas : public ifc_canvas +{ +protected: + Canvas(); +public: + virtual ~Canvas(); + +// ifc_canvas stuff + HDC getHDC(); + ifc_window *getRootWnd(); + void *getBits(); + void getOffsets(int *x, int *y); + bool isFixedCoords(); + bool getDim(int *w, int *h, int *p); + void setBaseWnd(BaseWnd *b); +// end ifc_canvas stuff + + virtual BaseWnd *getBaseWnd(); + + // graphics commands + void fillRect(const RECT *r, COLORREF color); + void fillRectAlpha(const RECT *r, COLORREF color, int alpha); + void fillRgn(RegionI *r, COLORREF color); + void drawRect(const RECT *r, int solid, COLORREF color, int alpha = 255); + + // text commands + const wchar_t *getTextFont(); + int getTextSize(); + int getTextBold(); + int getTextAntialias(); + int getTextOpaque(); + int getTextUnderline(); + int getTextItalic(); + int getTextAlign(); + COLORREF getTextColor(); + COLORREF getTextBkColor(); + + void pushPen(COLORREF color); + void pushPen(int style, int width, COLORREF color); + void popPen(); + + int getPenStyle(); + COLORREF getPenColor(); + int getPenWidth(); + + // normal text + void textOut(int x, int y, 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); + // returns height used + void textOutWrapped(int x, int y, int w, int h, const wchar_t *txt, const Wasabi::FontInfo *fontInfo); + void textOutWrappedPathed(int x, int y, int w, const wchar_t *txt, const Wasabi::FontInfo *fontInfo); + void textOutCentered(RECT *r, const wchar_t *txt, const Wasabi::FontInfo *fontInfo); + + int getTextWidth(const wchar_t *text, const Wasabi::FontInfo *fontInfo); + int getTextHeight(const wchar_t *text, const Wasabi::FontInfo *fontInfo); + void getTextExtent(const wchar_t *text, int *w, int *h, const Wasabi::FontInfo *fontInfo); + int getTextHeight(const Wasabi::FontInfo *fontInfo) + { + return getTextHeight(L"M", fontInfo); + } + + void selectClipRgn(api_region *r); + int getClipBox(RECT *r); // returns 0 if no clipping region + int getClipRgn(api_region *r); // returns 0 if no clipping region + + // Deprecated? + void moveTo(int x, int y); + void lineTo(int x, int y); + + void lineDraw(int fromX, int fromY, int toX, int toY); + + void drawSysObject(const RECT *r, int sysobj, int alpha = 255); + + void blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth); + void blitAlpha(ifc_canvas *canvas, int x, int y, int alpha = 255); + void blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha = 255); + void stretch(ifc_canvas *canvas, int x, int y, int w, int h); + // src* are in 16.16 fixed point + 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 antiAliasTo(Canvas *dest, int w, int h, int aafactor); + + int getXOffset() const + { + return xoffset; + } + int getYOffset() const + { + return yoffset; + } + void offsetRect(RECT *r); + void debug(); + + void colorToColor(COLORREF from, COLORREF to, RECT *r); + double getSystemFontScale(); + static void premultiply(ARGB32 *m_pBits, int nwords, int newalpha = -1); + +protected: + const Wasabi::FontInfo *getFontInfo() + { + if (userFontInfo) + return userFontInfo; + else + return &canvasFontInfo; + } + + RECVS_DISPATCH; + + HDC hdc; + void *bits; + int width, height, pitch; + bool fcoord; + int xoffset, yoffset; + BaseWnd *srcwnd; + Wasabi::FontInfo canvasFontInfo; // to hold our defaults + const Wasabi::FontInfo *userFontInfo; // passed from someone calling this function. usually is NULL + +private: + Stack<penstruct> penstack; + + int penstyle; + COLORREF pencolor; + int penwidth; + +#ifdef WIN32 + HPEN defpen; + HPEN curpen; +#endif +#ifdef LINUX + int raster_x, raster_y; +#endif + +}; + +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, +}; +}; + +class TATAKIAPI WndCanvas : public Canvas +{ +public: + WndCanvas(); + WndCanvas(BaseWnd *basewnd); + virtual ~WndCanvas(); + + // address client area + int attachToClient(BaseWnd *basewnd); +//CUT // address entire window +//CUT int attachToWnd(HWND _hWnd); // NONPORTABLE: avoid! mostly for mainwnd + +private: + HWND hWnd; +}; + +class TATAKIAPI PaintCanvas : public Canvas +{ +public: + PaintCanvas(); + virtual ~PaintCanvas(); + + int beginPaint(BaseWnd *basewnd); + int beginPaint(HWND wnd); + void getRcPaint(RECT *r); + +private: // NONPORTABLE + HWND hWnd; + PAINTSTRUCT ps; +}; + +class BltCanvas; +class TATAKIAPI PaintBltCanvas : public Canvas +{ +public: + PaintBltCanvas(); + virtual ~PaintBltCanvas(); + int beginPaint(BaseWnd *basewnd); + int beginPaintNC(BaseWnd *basewnd); + + void *getBits(); + void getRcPaint(RECT *r); + +private: // NONPORTABLE + HWND hWnd; + PAINTSTRUCT ps; + HDC wnddc; + HBITMAP hbmp, prevbmp; + bool nonclient; +#ifdef LINUX + BltCanvas *blitter; +#endif +}; + +class TATAKIAPI MemCanvas : public Canvas +{ +public: + MemCanvas(); + virtual ~MemCanvas(); + + int createCompatible(Canvas *canvas); +private: +}; + +class TATAKIAPI DCCanvas : public Canvas +{ +public: + DCCanvas(HDC clone = NULL, BaseWnd *srcWnd = NULL); + virtual ~DCCanvas(); + + int cloneDC(HDC clone, BaseWnd *srcWnd = NULL); +}; + +class TATAKIAPI SysCanvas : public Canvas +{ +public: + SysCanvas(); + virtual ~SysCanvas(); +}; + +/* benski> + a quick Canvas class to be created on-the-fly when you need to retrieve information about fonts + e.g. getTextExtent + don't try to draw with it or bad things will happen. + +*/ +class TATAKIAPI TextInfoCanvas : public Canvas +{ +public: + TextInfoCanvas(BaseWnd *basewnd); + virtual ~TextInfoCanvas(); +private: + HWND hWnd; +}; + +class TATAKIAPI DCBltCanvas : public Canvas +{ +public: + DCBltCanvas(); + virtual ~DCBltCanvas(); + + int cloneDC(HDC clone, RECT *r, BaseWnd *srcWnd = NULL); + int setOrigDC(HDC neworigdc); // set to null to prevent commitdc on delete, non null to change destination dc + int commitDC(void); // allows commit to DC without deleting +#if 0 + int cloneCanvas(ifc_canvas *clone, RECT *r); +#endif + +protected: + HDC origdc; + RECT rect; + HBITMAP hbmp, prevbmp; +}; + +class TATAKIAPI DCExBltCanvas : public DCBltCanvas +{ +public: + DCExBltCanvas(HWND hWnd, HRGN hrgnClip, DWORD flags); + + ~DCExBltCanvas(); +private: + HWND hwnd; +}; + + +// note: getBaseWnd() returns NULL for this class +class TATAKIAPI BaseCloneCanvas : public Canvas +{ +public: + BaseCloneCanvas(ifc_canvas *cloner = NULL); + virtual ~BaseCloneCanvas(); + + int clone(ifc_canvas *cloner); +}; + + + +#ifdef WIN32 +class TATAKIAPI DDSurfaceCanvas : public Canvas +{ + +public: + + DDSurfaceCanvas(LPDIRECTDRAWSURFACE surface, int w, int h); + virtual ~DDSurfaceCanvas(); + + int isready(); + void enter(); + void exit(); + +private: + LPDIRECTDRAWSURFACE surf; + int _w, _h; +}; +#endif + +class TATAKIAPI BitsCanvas : public Canvas +{ +public: + BitsCanvas(void *_bits, int _w, int _h) + { + bits=_bits; + width=_w; + height=_h; + pitch=_w; + } +}; + +enum +{ + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT +}; + +#endif diff --git a/Src/tataki/canvas/win/win32_canvas.cpp b/Src/tataki/canvas/win/win32_canvas.cpp new file mode 100644 index 00000000..c3d2ad8b --- /dev/null +++ b/Src/tataki/canvas/win/win32_canvas.cpp @@ -0,0 +1,1489 @@ +#ifndef _WIN32 +#error this file is for windows only. Don't include it in your project/makefile for other platforms +#else +#include <tataki/export.h> +#include <tataki/api__tataki.h> +#include <tataki/blending/blending.h> +#include "canvas.h" +#include <tataki/bitmap/bitmap.h> +#include <tataki/region/region.h> +#include <api/wnd/basewnd.h> +#include <api/wnd/fontdef.h> +#include <api/wnd/paintsets.h> + +#include <bfc/assert.h> + +#include "bltcanvas.h" +#include <nsutil/alpha.h> +#include <nsutil/image.h> + +#define CBCLASS Canvas +START_DISPATCH; +CB(GETHDC, getHDC); +CB(GETROOTWND, getRootWnd); +CB(GETBITS, getBits); +VCB(GETOFFSETS, getOffsets); +CB(ISFIXEDCOORDS, isFixedCoords); +CB(GETDIM, getDim); +CB(GETTEXTFONT, getTextFont); +CB(GETTEXTSIZE, getTextSize); +CB(GETTEXTBOLD, getTextBold); +CB(GETTEXTOPAQUE, getTextOpaque); +CB(GETTEXTUNDERLINE, getTextUnderline); +CB(GETTEXTITALIC, getTextItalic); +CB(GETTEXTALIGN, getTextAlign); +CB(GETTEXTCOLOR, getTextColor); +CB(GETTEXTBKCOLOR, getTextBkColor); +CB(GETTEXTAA, getTextAntialias); +CB(GETCLIPBOX, getClipBox); +END_DISPATCH; +#undef CBCLASS + +//NONPORTABLE + +extern const wchar_t wasabi_default_fontnameW[]; + +Canvas::Canvas() + : hdc(NULL), + bits(NULL), + srcwnd(NULL), + fcoord(FALSE), + xoffset(0), yoffset(0), + width(0), + height(0), + pitch(0), + defpen(NULL), + curpen(NULL), + userFontInfo(0) +{ + + //tfont = new String; // using dynamic tfont here coz we need to manage em with stack, so stacking fonts won't take sizeof(String) and their destruction will not fuxor everything + //tfont->setValue(wasabi_default_fontname); +} + +Canvas::~Canvas() +{ + if (getHDC() && defpen != NULL) + { + SelectObject(getHDC(), defpen); + DeleteObject(curpen); + } + + if (!penstack.isempty()) + DebugStringW(L"Pen stack not empty in Canvas::~Canvas !"); +} + +void Canvas::setBaseWnd(BaseWnd *b) +{ + srcwnd = b; +} + +HDC Canvas::getHDC() +{ + return hdc; +} + +ifc_window *Canvas::getRootWnd() +{ + return srcwnd; +} + +void *Canvas::getBits() +{ + return bits; +} + +bool Canvas::getDim(int *w, int *h, int *p) +{ + if (w) *w = width; + if (h) *h = height; + if (p) *p = pitch; + return FALSE; +} + +void Canvas::getOffsets(int *x, int *y) +{ + if (x != NULL) *x = getXOffset(); + if (y != NULL) *y = getYOffset(); +} + +bool Canvas::isFixedCoords() +{ + return fcoord; +} + +BaseWnd *Canvas::getBaseWnd() +{ + return srcwnd; +} + +void Canvas::fillRgn(RegionI *r, COLORREF color) +{ + ASSERT(r != NULL); + HBRUSH brush = CreateSolidBrush(color); + FillRgn(hdc, r->getOSHandle(), brush); + DeleteObject(brush); +} + +void Canvas::fillRect(const RECT *r, COLORREF color) +{ + ASSERT(r != NULL); +#if 0 + HBRUSH brush; + if (color == RGB(0, 0, 0)) + { + FillRect(hdc, r, (HBRUSH)GetStockObject(BLACK_BRUSH)); + return ; + } + RECT rr = *r; + offsetRect(&rr); + + brush = CreateSolidBrush(color); + FillRect(hdc, &rr, brush); + DeleteObject(brush); +#else +// see: http://ooeygui.typepad.com/ooey_gui/2005/06/tip_fast_solid_.html +COLORREF clrOld = SetBkColor(hdc, color); +RECT rr = *r; +offsetRect(&rr); +ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rr, NULL, 0, NULL); +SetBkColor(hdc, clrOld); +#endif +} + +void Canvas::fillRectAlpha(const RECT *r, COLORREF color, int alpha) +{ + RECT blitr; + RECT clipr; + getClipBox(&clipr); + IntersectRect(&blitr, &clipr, r); + uint8_t *bits8 = (uint8_t *)(bits) + blitr.left*4 + blitr.top * pitch; + nsutil_image_FillRectAlpha_RGB32((RGB32 *)(bits8), pitch, blitr.right-blitr.left, blitr.bottom-blitr.top, color, alpha); +} + +void Canvas::drawRect(const RECT *r, int solid, COLORREF color, int alpha) +{ +#if 0 + unsigned int blah = (unsigned int)alpha; + color = RGBTOBGR(color); + color = (color & 0xFFFFFF) | (blah << 24); + BltCanvas::premultiply(&color, 1); + int ox, oy; + getOffsets(&ox, &oy); + int w, h, pitch; + getDim(&w, &h, &pitch); + RECT _r = *r; + _r.right = MIN<int>(r->right, w); + _r.bottom = MIN<int>(r->bottom, h); + int _l = r->bottom - r->top; + int m = _r.bottom - _r.top; + int l = _l; + pitch /= 4; + int *p = (int *)bits + ox + r->left + (oy + r->top) * pitch; + int n = r->right - r->left; + int maxn = _r.right - _r.left; + while (l-- && m--) + { + int _n = maxn; + if (l == _l - 1 || !l) + { + if (solid) + { + while (_n--) + { + *p = Blenders::BLEND_ADJ2(*p, color); + p++; + } + } + else + { + while (_n--) + { + if (_n % 2) *p = Blenders::BLEND_ADJ2(*p, color); + p++; + } + } + p += n - maxn; + } + else + { + if (solid || l % 2) + *p = Blenders::BLEND_ADJ2(*p, color); + p += n - 1; + if (n == maxn && (solid || l % 2)) + *p = Blenders::BLEND_ADJ2(*p, color); + p++; + } + p += pitch - n; + } +#else +HBRUSH oldbrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH)); +HPEN oldpen, pen; +pen = CreatePen(solid ? PS_SOLID : PS_DOT, 0, color); +oldpen = (HPEN)SelectObject(hdc, pen); +ASSERT(r != NULL); +RECT rr = *r; +offsetRect(&rr); +Rectangle(hdc, rr.left, rr.top, rr.right, rr.bottom); +SelectObject(hdc, oldpen); +SelectObject(hdc, oldbrush); +DeleteObject(pen); +#endif +} + +int Canvas::getTextAlign() +{ + return getFontInfo()->alignFlags; +} + +int Canvas::getTextOpaque() +{ + return getFontInfo()->opaque; +} + + +int Canvas::getTextUnderline() +{ + return getFontInfo()->underline; +} + +int Canvas::getTextItalic() +{ + return getFontInfo()->italic; +} + +int Canvas::getTextBold() +{ + return getFontInfo()->bold; +} + +int Canvas::getTextAntialias() +{ + return getFontInfo()->antialias; +} + +void Canvas::pushPen(COLORREF color) +{ + pushPen(PENSTYLE_SOLID, 1, color); +} + +void Canvas::pushPen(int style, int width, COLORREF color) +{ + ASSERT(getHDC() != NULL); + penstyle = style; + penwidth = width; + pencolor = color; + penstruct s; + curpen = CreatePen(style, width, color); + HPEN oldpen = (HPEN)SelectObject(getHDC(), curpen); + s.style = style; + s.width = width; + s.color = color; + s.hpen = oldpen; + penstack.push(s); +} + +void Canvas::popPen() +{ + ASSERT(getHDC() != NULL); + if (penstack.isempty()) return ; + penstruct s; + penstack.pop(&s); + SelectObject(getHDC(), s.hpen); + DeleteObject(curpen); +} + +int Canvas::getPenStyle() +{ + return penstyle; +} + +COLORREF Canvas::getPenColor() +{ + return pencolor; +} + +int Canvas::getPenWidth() +{ + return penwidth; +} + +COLORREF Canvas::getTextColor() +{ + return getFontInfo()->color; +} + +COLORREF Canvas::getTextBkColor() +{ + return getFontInfo()->bgColor; +} + +int Canvas::getTextSize() +{ + return getFontInfo()->pointSize; +} + +const wchar_t *Canvas::getTextFont() +{ + return getFontInfo()->face; +} + +void Canvas::moveTo(int x, int y) +{ + MoveToEx(hdc, x, y, NULL); +} + +void Canvas::lineTo(int x, int y) +{ + LineTo(hdc, x, y); +} + +void Canvas::lineDraw(int fromX, int fromY, int toX, int toY) +{ + MoveToEx(hdc, fromX, fromY, NULL); + LineTo(hdc, toX, toY); +} + +void Canvas::drawSysObject(const RECT *r, int sysobj, int alpha) +{ +#ifndef _NOSTUDIO + RECT i_dont_trust_ms_with_my_rect = *r; + switch (sysobj) + { + case DrawSysObj::BUTTON: + WASABI_API_WND->paintset_render(Paintset::BUTTONUP, this, r, alpha); + break; + case DrawSysObj::BUTTON_PUSHED: + WASABI_API_WND->paintset_render(Paintset::BUTTONDOWN, this, r, alpha); + break; + case DrawSysObj::BUTTON_DISABLED: + WASABI_API_WND->paintset_render(Paintset::BUTTONDISABLED, this, r, alpha); + break; +#ifdef WIN32 + case DrawSysObj::OSBUTTON: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_BUTTON, DFCS_BUTTONPUSH); + } + break; + case DrawSysObj::OSBUTTON_PUSHED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED); + } + break; + case DrawSysObj::OSBUTTON_DISABLED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_INACTIVE); + } + break; + + case DrawSysObj::OSBUTTON_CLOSE: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONCLOSE); + } + break; + case DrawSysObj::OSBUTTON_CLOSE_PUSHED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_PUSHED); + } + break; + case DrawSysObj::OSBUTTON_CLOSE_DISABLED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INACTIVE); + } + break; + + case DrawSysObj::OSBUTTON_MINIMIZE: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONMIN); + } + break; + case DrawSysObj::OSBUTTON_MINIMIZE_PUSHED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_PUSHED); + } + break; + case DrawSysObj::OSBUTTON_MINIMIZE_DISABLED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INACTIVE); + } + break; + + case DrawSysObj::OSBUTTON_MAXIMIZE: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONMAX); + } + break; + case DrawSysObj::OSBUTTON_MAXIMIZE_PUSHED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_PUSHED); + } + break; + case DrawSysObj::OSBUTTON_MAXIMIZE_DISABLED: + { + DrawFrameControl(getHDC(), &i_dont_trust_ms_with_my_rect, DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_INACTIVE); + } + break; +#else +#error port me! +#endif + break; + } +#endif +} + +void Canvas::textOut(int x, int y, const wchar_t *txt, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_textOut(this, WA_FONT_TEXTOUT_NORMAL, x, y, 0, 0, txt); + userFontInfo = 0; +} + +void Canvas::textOut(int x, int y, int w, int h, const wchar_t *txt, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_textOut(this, WA_FONT_TEXTOUT_RECT, x, y, w, h, txt); + userFontInfo = 0; +} + +void Canvas::textOutEllipsed(int x, int y, int w, int h, const wchar_t *txt, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_textOut(this, WA_FONT_TEXTOUT_ELLIPSED, x, y, w, h, txt); + userFontInfo = 0; +} + +void Canvas::textOutWrapped(int x, int y, int w, int h, const wchar_t *txt, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_textOut(this, WA_FONT_TEXTOUT_WRAPPED, x, y, w, h, (txt)); + userFontInfo = 0; +} + +void Canvas::textOutWrappedPathed(int x, int y, int w, const wchar_t *txt, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_textOut(this, WA_FONT_TEXTOUT_WRAPPEDPATHED, x, y, w, 0, (txt)); + userFontInfo = 0; +} + +void Canvas::textOutCentered(RECT *r, const wchar_t *txt, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_textOut(this, WA_FONT_TEXTOUT_CENTERED, r->left, r->top, r->right, r->bottom, (txt)); + userFontInfo = 0; +} + +int Canvas::getTextWidth(const wchar_t *text, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + int ret = WASABI_API_FONT->font_getInfo(this, fontInfo->face, WA_FONT_GETINFO_WIDTH, (text), NULL, NULL); + userFontInfo = 0; + return ret; +} + +int Canvas::getTextHeight(const wchar_t *text, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + int ret = WASABI_API_FONT->font_getInfo(this, fontInfo->face, WA_FONT_GETINFO_HEIGHT, (text), NULL, NULL); + userFontInfo = 0; + return ret; +} + +void Canvas::getTextExtent(const wchar_t *txt, int *w, int *h, const Wasabi::FontInfo *fontInfo) +{ + userFontInfo = fontInfo; + WASABI_API_FONT->font_getInfo(this, fontInfo->face, WA_FONT_GETINFO_WIDTHHEIGHT, (txt), w, h); + userFontInfo = 0; +} + +void Canvas::offsetRect(RECT *r) +{ + ASSERT(r != NULL); + r->left += xoffset; + r->right += xoffset; + r->top += yoffset; + r->bottom += yoffset; +} + +void Canvas::selectClipRgn(api_region *r) +{ + SelectClipRgn(hdc, r ? r->getOSHandle() : NULL); +} + +int Canvas::getClipBox(RECT *r) +{ + RECT dummy; + if (!r) r = &dummy; + return GetClipBox(hdc, r); +} + +int Canvas::getClipRgn(api_region *r) +{ + ASSERT(r != NULL); + return GetClipRgn(hdc, r->getOSHandle()); +} + +//FG> added blit canvas to canvas +void Canvas::blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth) +{ + char *srcbits = (char *)getBits(); + char *destbits = (char *)dest->getBits(); + RECT clipr; + if (srcbits && destbits && GetClipBox(dest->getHDC(), &clipr) == SIMPLEREGION) + { + int srcimg_w, srcimg_h, srcimg_p; + getDim(&srcimg_w, &srcimg_h, &srcimg_p); + int dstimg_w, dstimg_h, dstimg_p; + dest->getDim(&dstimg_w, &dstimg_h, &dstimg_p); + + if (srcx < 0) + { + dstx -= srcx; dstw += srcx; srcx = 0; + } + if (srcy < 0) + { + dsty -= srcy; dsth += srcy; srcy = 0; + } + if (srcx + dstw >= srcimg_w) dstw = srcimg_w - srcx; + if (srcy + dsth >= srcimg_h) dsth = srcimg_h - srcy; + + if (dstx < clipr.left) + { + srcx += clipr.left - dstx; dstw -= clipr.left - dstx; dstx = clipr.left; + } + if (dsty < clipr.top) + { + srcy += clipr.top - dsty; dsth -= clipr.top - dsty; dsty = clipr.top; + } + + if (dstx + dstw >= clipr.right) dstw = clipr.right - dstx; + if (dsty + dsth >= clipr.bottom) dsth = clipr.bottom - dsty; + + if (!dstw || !dsth) return ; + + int y; + int yl = dsty + dsth; + for (y = dsty; y < yl; y++) + { + MEMCPY32(destbits + y*dstimg_p + dstx*4, srcbits + srcy*srcimg_p + srcx*4, dstw); + srcy++; + } + } + else + { + //GdiFlush(); + BitBlt(dest->getHDC(), dstx, dsty, dstw, dsth, getHDC(), srcx, srcy, SRCCOPY); + } +} + +#pragma comment(lib, "msimg32.lib") + +void Canvas::stretch(ifc_canvas *canvas, int x, int y, int w, int h) +{ + if (bits) + { + SkinBitmap temp((ARGB32 *)bits, width, height); + temp.stretch(canvas, x,y,w,h); + } + else + { + BLENDFUNCTION blendFn; + blendFn.BlendOp = AC_SRC_OVER; + blendFn.BlendFlags = 0; + blendFn.SourceConstantAlpha = 255; + blendFn.AlphaFormat = AC_SRC_ALPHA; + + AlphaBlend(canvas->getHDC(), + x, y, + w, h, + getHDC(), + 0, 0, + width, height, + blendFn); + } +} + +void Canvas::blitAlpha(ifc_canvas *canvas, int x, int y, int alpha) +{ + if (bits) + { + SkinBitmap temp((ARGB32 *)bits, width, height); + temp.blitAlpha(canvas, x,y,alpha); + } + else + { + BLENDFUNCTION blendFn; + blendFn.BlendOp = AC_SRC_OVER; + blendFn.BlendFlags = 0; + blendFn.SourceConstantAlpha = alpha; + blendFn.AlphaFormat = AC_SRC_ALPHA; + + AlphaBlend(canvas->getHDC(), + x, y, + width, height, + getHDC(), + 0, 0, + width, height, + blendFn); + } +} + +void Canvas::stretchToRectAlpha(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha) +{ + if (bits) + { + SkinBitmap temp((ARGB32 *)bits, width, height); + temp.stretchToRectAlpha(canvas, src, dst, alpha); + } + else + { + BLENDFUNCTION blendFn; + blendFn.BlendOp = AC_SRC_OVER; + blendFn.BlendFlags = 0; + blendFn.SourceConstantAlpha = alpha; + blendFn.AlphaFormat = AC_SRC_ALPHA; + + AlphaBlend(canvas->getHDC(), + dst->left, dst->top, + dst->right - dst->left, dst->bottom - dst->top, + getHDC(), + src->left, src->top, + src->right - src->left, src->bottom - src->top, + blendFn); + } +} + +void Canvas::blitToRect(ifc_canvas *canvas, RECT *src, RECT *dst, int alpha) +{ + if (bits) + { + SkinBitmap temp((ARGB32 *)bits, width, height); + temp.blitToRect(canvas, src, dst, alpha); + } + else + { + BLENDFUNCTION blendFn; + blendFn.BlendOp = AC_SRC_OVER; + blendFn.BlendFlags = 0; + blendFn.SourceConstantAlpha = alpha; + blendFn.AlphaFormat = AC_SRC_ALPHA; + + AlphaBlend(canvas->getHDC(), + dst->left, dst->top, + dst->right - dst->left, dst->bottom - dst->top, + getHDC(), + src->left, src->top, + src->right - src->left, src->bottom - src->top, + blendFn); + } +} + +// src* are in fixed point +static void scale_internal(int srcx, int srcy, int srcw, int srch, void *srcdib, int srcdib_w, int srcdib_h, int srcdib_p, int dstx, int dsty, int dstw, int dsth, void *dstdib, int nofilter) +{ + // scaling up + if ((dstw << 16) >= srcw && (dsth << 16) >= srch) + { + int y; + int SY, dX, dY; + int Xend = (srcdib_w - 2) << 16; + SY = srcy; + dX = srcw / dstw; + dY = srch / dsth; + + int xstart = 0; + int xp = srcx >> 16; + if (xp < 0) + { + xstart = -xp; + srcx += xstart * dX; + } + + int xend = dstw; + xp = (srcx + (dX * (xend - xstart))) >> 16; + if (xp > srcdib_w) + { + xend = xstart + srcdib_w - (srcx >> 16); + } + + for (y = 0; y < dsth; y ++) + { + int yp = (SY >> 16); + if (yp >= 0) + { + int x; + int SX = srcx; + unsigned int *out = (unsigned int*)dstdib + xstart + y * dstw; + int end = yp >= srcdib_h - 1; + if (nofilter || end) + { + if (end) yp = srcdib_h - 1; + unsigned int *in = (unsigned int*)((char *)srcdib + yp * srcdib_p); + for (x = xstart; x < xend; x ++) // quick hack to draw last line + { + *out++ = in[SX >> 16]; + SX += dX; + } + if (end) break; + } + else + { + unsigned int *in = (unsigned int*)((char *)srcdib + yp * srcdib_p); + +#ifndef NO_MMX + if (Blenders::MMX_AVAILABLE()) + { + for (x = xstart; x < xend; x ++) + { + if (SX > Xend) *out++ = Blenders::BLEND4_MMX(in + (Xend >> 16), srcdib_w, 0xffff, SY); + else *out++ = Blenders::BLEND4_MMX(in + (SX >> 16), srcdib_w, SX, SY); + SX += dX; + } + } + else +#endif + + { + for (x = xstart; x < xend; x ++) + { + if (SX > Xend) *out++ = Blenders::BLEND4(in + (Xend >> 16), srcdib_w, 0xffff, SY); + else *out++ = Blenders::BLEND4(in + (SX >> 16), srcdib_w, SX, SY); + SX += dX; + } + } + } + } + SY += dY; + } + // end of scaling up + } + else // we are scaling down -- THIS IS SLOW AND MAY BREAK THINGS. :) + { + int y; + int SY, dX, dY; + SY = srcy; + dX = srcw / dstw; + dY = srch / dsth; + + int xstart = 0; + int xp = srcx >> 16; + if (xp < 0) + { + xstart = -xp; + srcx += xstart * dX; + } + + int xend = dstw; + xp = (srcx + (dX * (xend - xstart))) >> 16; + if (xp > srcdib_w) + { + xend = xstart + srcdib_w - (srcx >> 16); + } + + for (y = 0; y < dsth; y ++) + { + // start and end of y source block + int vStart = SY; + int vEnd = SY + dY; + + int x; + int SX = srcx; + unsigned char *out = (unsigned char *)((unsigned int*)dstdib + xstart + y * dstw); + for (x = xstart; x < xend; x ++) + { + if (((char *)out+4) >= ((char *)dstdib + 4*dstw*dsth)) + break; + int uStart = SX; + int uEnd = SX + dX; + // calculate sum of rectangle. + + int cnt = 0; + __int64 accum[4] = {0, }; + int v, u; + for (v = vStart; v < vEnd; v += 65536) + { + unsigned int vscale = 65535; + + if (v == vStart) + { + vscale = 65535 - (v & 0xffff); + } + else if ((vEnd - v) < 65536) + { + vscale = (vEnd - v) & 0xffff; + } + + int vp = v >> 16; + unsigned char *in = (unsigned char*)((char *)srcdib + vp * srcdib_p + 4 * (uStart >> 16)); + for (u = uStart; u < uEnd; u += 65536) + { + if (((char *)in+4) >= ((char *)srcdib + srcdib_p*srcdib_h)) + break; + unsigned int uscale = vscale; + if (u == uStart) + { + uscale *= 65535 - (u & 0xffff); + uscale >>= 16; + } + else if ((uEnd - u) < 65536) + { + uscale *= (uEnd - u) & 0xffff; + uscale >>= 16; + } + cnt += uscale; + if (uscale == 65535) + { + accum[0] += (in[0] << 16) - in[0]; + accum[1] += (in[1] << 16) - in[1]; + accum[2] += (in[2] << 16) - in[2]; + accum[3] += (in[3] << 16) - in[3]; + } + else + { + accum[0] += in[0] * uscale; + accum[1] += in[1] * uscale; + accum[2] += in[2] * uscale; + accum[3] += in[3] * uscale; + } + in += 4; + } + } + if (!cnt) cnt++; + + out[0] = (uint8_t)(accum[0] / cnt); + out[1] = (uint8_t)(accum[1] / cnt); + out[2] = (uint8_t)(accum[2] / cnt); + out[3] = (uint8_t)(accum[3] / cnt); + out += 4; + + SX += dX; + } + SY += dY; + } + // end of scaling down + } + +#ifndef NO_MMX + Blenders::BLEND_MMX_END(); +#endif +} + + +// src* are in fixed point +void Canvas::stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth) +{ + //GdiFlush(); + int done = 0; + void *srcdib = getBits(); + + if (!dstw || !dsth || !srcw || !srch) return ; + if (srcdib) + { + int srcdib_w, srcdib_h, srcdib_p; + getDim(&srcdib_w, &srcdib_h, &srcdib_p); + + void *dstdib; + BITMAPINFO dstbmi = {0}; + HDC hMemDC; + HBITMAP hsrcdib; + dstbmi.bmiHeader.biSize = sizeof(dstbmi.bmiHeader); + dstbmi.bmiHeader.biWidth = dstw; + dstbmi.bmiHeader.biHeight = -ABS(dsth); + dstbmi.bmiHeader.biPlanes = 1; + dstbmi.bmiHeader.biBitCount = 32; + dstbmi.bmiHeader.biCompression = BI_RGB; + hMemDC = CreateCompatibleDC(NULL); + hsrcdib = CreateDIBSection(hMemDC, &dstbmi, DIB_RGB_COLORS, &dstdib, NULL, 0); + if (hsrcdib) + { + HBITMAP hprev = (HBITMAP)SelectObject(hMemDC, hsrcdib); + + scale_internal(srcx,srcy,srcw,srch,srcdib,srcdib_w,srcdib_h,srcdib_p,dstx,dsty,dstw,dsth,dstdib,0); + + BitBlt(dest->getHDC(), dstx, dsty, dstw, dsth, hMemDC, 0, 0, SRCCOPY); + done++; + + SelectObject(hMemDC, hprev); + DeleteObject(hsrcdib); + } + DeleteDC(hMemDC); + } + + if (!done) + { + SetStretchBltMode(dest->getHDC(), COLORONCOLOR); + StretchBlt(dest->getHDC(), dstx, dsty, dstw, dsth, getHDC(), srcx >> 16, srcy >> 16, srcw >> 16, srch >> 16, SRCCOPY); + } +} + +#define DEBUG_SCREEN_SHIFT 0 +void Canvas::debug() +{ + SysCanvas c; + int w, h; + getDim(&w, &h, NULL); + blit(0, 0, &c, DEBUG_SCREEN_SHIFT, 0, w, h); +} + +#define BF2 (~((3<<24)|(3<<16)|(3<<8)|3)) + +void Canvas::antiAliasTo(Canvas *dest, int w, int h, int aafactor) +{ + ASSERT(aafactor != 0); + if (aafactor == 1) + { + blit(0, 0, dest, 0, 0, w, h); + return ; + } + ASSERT(getBits() != NULL); + ASSERT(dest->getBits() != NULL); + if (getBits() == NULL || dest->getBits() == NULL) return ; + ASSERTPR(aafactor <= 2, "too lazy to generalize the code right now :)"); + //GdiFlush(); + // we should really store the bpp too + int aaw = w * aafactor; + unsigned long *s1 = (unsigned long *)getBits(), *s2 = s1 + 1; + unsigned long *s3 = s1 + aaw, *s4 = s3 + 1; + unsigned long *d = (unsigned long *)dest->getBits(); +#if 1 + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + unsigned long tmp = ((*s1 & BF2) >> 2) + ((*s2 & BF2) >> 2) + ((*s3 & BF2) >> 2) + ((*s4 & BF2) >> 2); + *d++ = tmp; + + s1 += 2; s2 += 2; + s3 += 2; s4 += 2; + } + s1 += aaw; s2 += aaw; + s3 += aaw; s4 += aaw; + } +#else +for (int x = 0; x < w * h; x++) d[x] = s1[x]; +#endif +} + +void Canvas::colorToColor(COLORREF from, COLORREF to, RECT *r) +{ + int w, h, ox, oy; + + // convert to bitmap order + from = RGBTOBGR(from); + to = RGBTOBGR(to); + + COLORREF *p; + getDim(&w, &h, NULL); + p = (COLORREF *)getBits(); + getOffsets(&ox, &oy); + p += ox + r->left + (oy + r->top) * w; + int rw = r->right - r->left; + for (int j = r->top;j < r->bottom;j++) + { + for (int i = r->left;i < r->right;i++) + { + if (*p == from) + *p = to; + p++; + } + p += w - rw; + } +} + +double Canvas::getSystemFontScale() +{ + if (WASABI_API_CONFIG) + { + int v = WASABI_API_CONFIG->getIntPublic(L"manualsysmetrics", -1); + if (v != -1) return (v / 100.0f); + } + + int nLogDPIX = GetDeviceCaps(getHDC(), LOGPIXELSX); + return ((float)nLogDPIX / 96.0f); +} + +void Canvas::premultiply(ARGB32 *m_pBits, int nwords, int newalpha) +{ + if (newalpha == -1) + { + nsutil_alpha_Premultiply_RGB32(m_pBits, nwords, nwords, 1); + /* + for (; nwords > 0; nwords--, m_pBits++) + { + unsigned char *pixel = (unsigned char *)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 + } + */ + } + else + { + nsutil_alpha_PremultiplyValue_RGB8(m_pBits, nwords, nwords, 1, newalpha); + /* + for (; nwords > 0; nwords--, m_pBits++) + { + unsigned char *pixel = (unsigned char *)m_pBits; + pixel[0] = (pixel[0] * newalpha) >> 8; // blue + pixel[1] = (pixel[1] * newalpha) >> 8; // green + pixel[2] = (pixel[2] * newalpha) >> 8; // red + pixel[3] = (pixel[3] * newalpha) >> 8; // alpha + } + */ + } +} + +TextInfoCanvas::TextInfoCanvas(BaseWnd *basewnd) +{ + ASSERT(basewnd != NULL); + hWnd = basewnd->gethWnd(); + hdc = GetDC(hWnd); +} + +TextInfoCanvas::~TextInfoCanvas() +{ + if (hdc) + ReleaseDC(hWnd, hdc); +} + +WndCanvas::WndCanvas(BaseWnd *basewnd) +{ + attachToClient(basewnd); +} + +WndCanvas::WndCanvas() +{ + hWnd = NULL; +} + +WndCanvas::~WndCanvas() +{ + if (hWnd != NULL && hdc != NULL) ReleaseDC(hWnd, hdc); + hdc = NULL; +} + +int WndCanvas::attachToClient(BaseWnd *basewnd) +{ + if (basewnd == NULL) + return 0; + + hWnd = basewnd->gethWnd(); + if (hWnd == NULL) + return 0; + + hdc = GetDC(hWnd); + if (hdc == NULL) + return 0; + + srcwnd = basewnd; + return 1; +} + +#if 0//CUT +int WndCanvas::attachToWnd(HWND _hWnd) +{ + hWnd = _hWnd; + ASSERT(hWnd != NULL); + hdc = GetWindowDC(hWnd); + ASSERT(hdc != NULL); + return 1; +} +#endif + +PaintCanvas::PaintCanvas() +{ + hWnd = NULL; +} + +PaintCanvas::~PaintCanvas() +{ + + if (hdc != NULL) EndPaint(hWnd, &ps); + hdc = NULL; +} + +void PaintCanvas::getRcPaint(RECT *r) +{ + *r = ps.rcPaint; +} + +int PaintCanvas::beginPaint(BaseWnd *basewnd) +{ + hWnd = basewnd->gethWnd(); // NONPORTABLE + ASSERT(hWnd != NULL); + hdc = BeginPaint(hWnd, &ps); + ASSERT(hdc != NULL); + srcwnd = basewnd; + return 1; +} + +int PaintCanvas::beginPaint(HWND wnd) +{ + hWnd = wnd; // NONPORTABLE + ASSERT(hWnd != NULL); + hdc = BeginPaint(hWnd, &ps); + ASSERT(hdc != NULL); + srcwnd = NULL; + return 1; +} + +PaintBltCanvas::PaintBltCanvas() +{ + hWnd = NULL; + wnddc = NULL; + hbmp = NULL; + prevbmp = NULL; + bits = NULL; + fcoord = TRUE; + nonclient = FALSE; +} + +PaintBltCanvas::~PaintBltCanvas() +{ + RECT r; + + if (hdc == NULL) return ; + + ASSERT(srcwnd != NULL); + if (nonclient) //FG> nonclient painting fix + srcwnd->getNonClientRect(&r); + else + srcwnd->getClientRect(&r); + + // blt here + //GdiFlush(); + BitBlt(wnddc, r.left, r.top, r.right - r.left, r.bottom - r.top, hdc, 0, 0, SRCCOPY); + + //SelectClipRgn(hdc, NULL); + // kill the bitmap and its DC + SelectObject(hdc, prevbmp); + DeleteDC(hdc); + hdc = NULL; + DeleteObject(hbmp); + bits = NULL; + width = 0; + height = 0; + pitch = 0; + + EndPaint(hWnd, &ps); // end of wnddc + wnddc = NULL; +} + +//FG> nonclient painting fix +int PaintBltCanvas::beginPaintNC(BaseWnd *basewnd) +{ + nonclient = TRUE; + return beginPaint(basewnd); +} + +void PaintBltCanvas::getRcPaint(RECT *r) +{ + *r = ps.rcPaint; +} + +int PaintBltCanvas::beginPaint(BaseWnd *basewnd) +{ + + RECT r; + + if (nonclient) + basewnd->getNonClientRect(&r); //FG> nonclient painting fix + else + basewnd->getClientRect(&r); + + if (r.right - r.left <= 0 || r.bottom - r.top <= 0) return 0; + + hWnd = basewnd->gethWnd(); // NONPORTABLE + ASSERT(hWnd != NULL); + + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof bmi); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = r.right - r.left; + bmi.bmiHeader.biHeight = -(r.bottom - r.top); + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = 0; + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + wnddc = BeginPaint(hWnd, &ps); + + ASSERT(wnddc != NULL); + + //GdiFlush(); + width = r.right - r.left; + height = -ABS(r.bottom - r.top); + pitch = width * 4; + hbmp = CreateDIBSection(wnddc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0); + + if (hbmp == NULL) + { + EndPaint(hWnd, &ps); // end of wnddc + wnddc = NULL; + return 0; + } + + // create tha DC + hdc = CreateCompatibleDC(wnddc); + if (hdc == NULL) + { + DeleteObject(hbmp); + EndPaint(hWnd, &ps); // end of wnddc + wnddc = NULL; + return 0; + } + prevbmp = (HBITMAP)SelectObject(hdc, hbmp); + + RegionI clip(&ps.rcPaint); + + selectClipRgn(&clip); + + srcwnd = basewnd; + + return 1; +} + +void *PaintBltCanvas::getBits() +{ + return bits; +} + +MemCanvas::MemCanvas() +{} + +MemCanvas::~MemCanvas() +{ + DeleteDC(hdc); + hdc = NULL; +} + +int MemCanvas::createCompatible(Canvas *canvas) +{ + ASSERT(canvas != NULL); + ASSERT(canvas->getHDC() != NULL); + hdc = CreateCompatibleDC(canvas->getHDC()); + ASSERT(hdc != NULL); + srcwnd = canvas->getBaseWnd(); + return 1; +} + + +DCCanvas::DCCanvas(HDC clone, BaseWnd *srcWnd) +{ + if (clone != NULL) cloneDC(clone, srcWnd); +} + +DCCanvas::~DCCanvas() +{ + hdc = NULL; +} + +int DCCanvas::cloneDC(HDC clone, BaseWnd *srcWnd) +{ + ASSERT(clone != NULL); + hdc = clone; + srcwnd = srcWnd; + return 1; +} + +SysCanvas::SysCanvas() +{ + hdc = GetDC(NULL); +} + +SysCanvas::~SysCanvas() +{ + ReleaseDC(NULL, hdc); + hdc = NULL; +} + +DCBltCanvas::DCBltCanvas() +{ + origdc = NULL; + hbmp = prevbmp = NULL; +} + +DCBltCanvas::~DCBltCanvas() +{ + + commitDC(); + + // kill the bitmap and its DC + SelectObject(hdc, prevbmp); + DeleteDC(hdc); + hdc = NULL; + DeleteObject(hbmp); + + // don't kill origdc, it's been cloned +} + +int DCBltCanvas::setOrigDC(HDC neworigdc) +{ + // FG> allows custom draw on lists to be much faster + origdc = neworigdc; + return 1; +} + +int DCBltCanvas::commitDC(void) +{ + //FG + + if (origdc) + { + + RECT c; + + if (GetClipBox(origdc, &c) == NULLREGION) + c = rect; + + // shlap it down in its original spot + //GdiFlush(); + BitBlt(origdc, c.left, c.top, + c.right - c.left, c.bottom - c.top, hdc, c.left-rect.left, c.top-rect.top, SRCCOPY); + + } + + return 1; +} + +int DCBltCanvas::cloneDC(HDC clone, RECT *r, BaseWnd *srcWnd) +{ + origdc = clone; + + srcwnd = srcWnd; + + ASSERT(r != NULL); + rect = *r; + +#if 1 + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof bmi); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = r->right - r->left; + bmi.bmiHeader.biHeight = -ABS(r->bottom - r->top); + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = 0; + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + hbmp = CreateDIBSection(origdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0); + width = bmi.bmiHeader.biWidth; + height = ABS(bmi.bmiHeader.biHeight); + pitch = width * 4; +#else +hbmp = CreateCompatibleBitmap(clone, r->right - r->left, r->bottom - r->top); +#endif + ASSERT(hbmp != NULL); + + // create tha DC + hdc = CreateCompatibleDC(origdc); + prevbmp = (HBITMAP)SelectObject(hdc, hbmp); + + // adjust their rect for them + r->right -= r->left; + r->left = 0; + r->bottom -= r->top; + r->top = 0; + + return 1; +} + +DCExBltCanvas::DCExBltCanvas(HWND hWnd, HRGN hrgnClip, DWORD flags) : hwnd(hWnd) +{ + origdc = GetDCEx(hWnd, hrgnClip, flags); + RECT r; + GetWindowRect(hWnd, &r); + OffsetRect(&r, -r.left, -r.top); + cloneDC(origdc, &r); +} + +DCExBltCanvas::~DCExBltCanvas() +{ + commitDC(); + ReleaseDC(hwnd, origdc); + origdc=0; +} + + +BaseCloneCanvas::BaseCloneCanvas(ifc_canvas *cloner) +{ + if (cloner != NULL) clone(cloner); +} + +int BaseCloneCanvas::clone(ifc_canvas *cloner) +{ + ASSERTPR(hdc == NULL, "can't clone twice"); + hdc = cloner->getHDC(); + bits = cloner->getBits(); + cloner->getDim(&width, &height, &pitch); + // srcwnd = cloner->getBaseWnd(); + cloner->getOffsets(&xoffset, &yoffset); + + canvasFontInfo.face = cloner->getTextFont(); // just copies the pointer so be careful + canvasFontInfo.pointSize = cloner->getTextSize(); + canvasFontInfo.bold = cloner->getTextBold(); + canvasFontInfo.opaque = !!cloner->getTextOpaque(); + canvasFontInfo.underline = !!cloner->getTextUnderline(); + canvasFontInfo.italic = !!cloner->getTextItalic(); + canvasFontInfo.alignFlags = cloner->getTextAlign(); + canvasFontInfo.color = cloner->getTextColor(); + canvasFontInfo.bgColor = cloner->getTextBkColor(); + + return (hdc != NULL); +} + +BaseCloneCanvas::~BaseCloneCanvas() +{ + hdc = NULL; +} + +DDSurfaceCanvas::DDSurfaceCanvas(LPDIRECTDRAWSURFACE surface, int w, int h) +{ + surf = surface; + _w = w; + _h = h; + hdc = NULL; + bits = NULL; +} + +DDSurfaceCanvas::~DDSurfaceCanvas() +{ + if (isready()) + exit(); +} + +int DDSurfaceCanvas::isready() +{ + return bits != NULL; +} + +void DDSurfaceCanvas::enter() +{ + DDSURFACEDESC d = {sizeof(d), }; + if ((surf->Lock(NULL, &d, DDLOCK_WAIT, NULL)) != DD_OK) + return ; + + surf->GetDC(&hdc); + + bits = d.lpSurface; +} + +void DDSurfaceCanvas::exit() +{ + surf->ReleaseDC(hdc); + surf->Unlock(bits); + bits = NULL; + hdc = NULL; +} + + +#endif//WIN32 diff --git a/Src/tataki/color/filteredcolor.cpp b/Src/tataki/color/filteredcolor.cpp new file mode 100644 index 00000000..119fe3b9 --- /dev/null +++ b/Src/tataki/color/filteredcolor.cpp @@ -0,0 +1,78 @@ +#include "filteredcolor.h" +#include <tataki/api__tataki.h> +#include <bfc/bfc_assert.h> + +static const int *skin_iterator=0; + +FilteredColor::FilteredColor(ARGB32 _color, const wchar_t *colorgroupname) +{ + group=0; + color = _color; + filteredcolor = _color; + if (colorgroupname) + group = _wcsdup(colorgroupname); + skin_iterator = NULL; + latest_iteration = -1; + need_filter = 1; +} + +FilteredColor::~FilteredColor() +{ + free(group); +} + +void FilteredColor::setColor(ARGB32 _color) +{ + color = _color; + filteredcolor = color; +} + +void FilteredColor::setColorGroup(const wchar_t *_group) +{ + free(group); + if (_group) + group = _wcsdup(_group); + else + group = 0; + need_filter = 1; +} + +ARGB32 FilteredColor::getColor() +{ + ensureFiltered(); + return filteredcolor; +} + +ARGB32 *FilteredColor::getColorRef() +{ + if (!WASABI_API_SKIN) + return 0; + + ensureFiltered(); + return &filteredcolor; +} + +void FilteredColor::ensureFiltered() +{ + // fetch iterator pointer if necessary + if (skin_iterator == NULL) + { + skin_iterator = WASABI_API_PALETTE->getSkinPartIteratorPtr(); + ASSERT(skin_iterator != NULL); + } + + // see if we're current + if (*skin_iterator != latest_iteration) + { + need_filter = 1; // pointer now invalid, must re-get + latest_iteration = *skin_iterator; // and then we'll be current + } + + if (need_filter && WASABI_API_SKIN) + { + filteredcolor = WASABI_API_SKIN->filterSkinColor(color, getColorName(), group); + need_filter = 0; + } + +} + diff --git a/Src/tataki/color/filteredcolor.h b/Src/tataki/color/filteredcolor.h new file mode 100644 index 00000000..9499b1c8 --- /dev/null +++ b/Src/tataki/color/filteredcolor.h @@ -0,0 +1,29 @@ +#ifndef TATAKI_FILTEREDCOLOR_H +#define TATAKI_FILTEREDCOLOR_H + +#include <tataki/export.h> + +class TATAKIAPI FilteredColor +{ +public: + FilteredColor(ARGB32 _color=0, const wchar_t *colorgroupname=L""); + virtual ~FilteredColor(); + + virtual void setColor(ARGB32 _color); + virtual void setColorGroup(const wchar_t *group); + ARGB32 getColor(); + ARGB32 *getColorRef(); + virtual const wchar_t *getColorName() { return NULL; } + +private: + void ensureFiltered(); + + ARGB32 color; + ARGB32 filteredcolor; + wchar_t *group; + int need_filter; + int latest_iteration; +}; + + +#endif diff --git a/Src/tataki/color/skinclr.cpp b/Src/tataki/color/skinclr.cpp new file mode 100644 index 00000000..9edacb85 --- /dev/null +++ b/Src/tataki/color/skinclr.cpp @@ -0,0 +1,134 @@ +#include "skinclr.h" +#include <bfc/assert.h> +#include <tataki/api__tataki.h> + +static const int *skin_iterator = 0; + +SkinColor::SkinColor(const wchar_t *_name, const wchar_t *colorgroup) +: FilteredColor(0, (colorgroup == NULL || !*colorgroup) ? L"Text" : colorgroup) +{ + name = 0; + latest_iteration = -1; + //CUT skin_iterator = NULL; + setElementName(_name); + ovr_grp = colorgroup; + dooverride = 0; + color_override = 0; + +} + +SkinColor::~SkinColor() +{ + if (name) free(name); +} + +ARGB32 SkinColor::v(ARGB32 defaultColor) +{ + if (!name || !*name) return defaultColor; + + if (!iteratorValid()) + { + val = NULL; // pointer now invalid, must re-get + latest_iteration = *skin_iterator; // and then we'll be current + // new pointer please + + const wchar_t *grp = NULL; + ARGB32 r; + if (dooverride) + r = color_override; + else + r = WASABI_API_PALETTE->getColorElement(name, &grp); + if (ovr_grp == NULL && grp != NULL) + setColorGroup(grp); + FilteredColor::setColor(r); + val = getColorRef(); + } + if (val == NULL) return defaultColor; + + return *val; +} + +void SkinColor::setElementName(const wchar_t *_name) +{ + if (name) free(name); + if (_name) + name = _wcsdup(_name); + else + name = 0; + val = NULL; + latest_iteration = 0; +} + +void SkinColor::setColor(ARGB32 c) +{ + dooverride = 1; + color_override = c; + FilteredColor::setColor(color_override); +} + +int SkinColor::iteratorValid() +{ + // fetch iterator pointer if necessary + if (skin_iterator == NULL) + { + skin_iterator = WASABI_API_PALETTE->getSkinPartIteratorPtr(); + ASSERT(skin_iterator != NULL); + } + + // see if we're current + return (*skin_iterator == latest_iteration); +} + +const wchar_t *SkinColor::operator =(const wchar_t *name) { setElementName(name); return name;} +const wchar_t *SkinColor::getColorName() { return name; } + +ARGB32 SkinColor::GetColor(const wchar_t *name, const wchar_t *group, ARGB32 defaultColor) +{ + const wchar_t *colorGroup = NULL; + const ARGB32 *color = WASABI_API_PALETTE->getColorElementRef(name, &colorGroup); + + if (!color) + return defaultColor; + + /* TODO: benski> if we ever add color themes to Classic, we'll need to change this */ + if (WASABI_API_SKIN) + { + if (group) + colorGroup = group; + + if (!colorGroup) + colorGroup = L"Text"; + + return WASABI_API_SKIN->filterSkinColor(*color, name, colorGroup); + } + else + { + return *color; + } +} + +bool SkinColor::TryGetColor(ARGB32 *returned_color, const wchar_t *name, const wchar_t *group) +{ + const wchar_t *colorGroup = NULL; + const ARGB32 *color = WASABI_API_PALETTE->getColorElementRef(name, &colorGroup); + + if (!color) + return false; + + /* TODO: benski> if we ever add color themes to Classic, we'll need to change this */ + if (WASABI_API_SKIN) + { + if (group) + colorGroup = group; + + if (!colorGroup) + colorGroup = L"Text"; + + *returned_color = WASABI_API_SKIN->filterSkinColor(*color, name, colorGroup); + } + else + { + *returned_color = *color; + } + return true; +}
\ No newline at end of file diff --git a/Src/tataki/color/skinclr.h b/Src/tataki/color/skinclr.h new file mode 100644 index 00000000..743eaa9c --- /dev/null +++ b/Src/tataki/color/skinclr.h @@ -0,0 +1,39 @@ +#ifndef TATAKI_SKINCLR_H +#define TATAKI_SKINCLR_H + +#include <tataki/export.h> +#include "filteredcolor.h" + +// note: only pass in a const char * +class TATAKIAPI SkinColor : public FilteredColor +{ +public: + explicit SkinColor(const wchar_t *name=NULL, const wchar_t *colorgroup=NULL); + ~SkinColor(); + virtual void setColor(ARGB32 c); + + ARGB32 v(ARGB32 defaultColor=0xFFFF00FF); + operator int() { return v(); } + + void setElementName(const wchar_t *name); + const wchar_t *operator =(const wchar_t *name); + virtual const wchar_t *getColorName(); + + int iteratorValid(); // if FALSE, color might have changed + + // if you just need to do a one-off skin color query, use this function +// because SkinColor class does some malloc'ing + static ARGB32 GetColor(const wchar_t *name, const wchar_t *group = 0, ARGB32 defaultColor=0xFFFF00FF); + static bool TryGetColor(ARGB32 *color, const wchar_t *name, const wchar_t *group = 0); +private: + wchar_t *name; + ARGB32 *val; + int latest_iteration; + const wchar_t *ovr_grp; + int color_override; + int dooverride; +}; + + + +#endif diff --git a/Src/tataki/export.h b/Src/tataki/export.h new file mode 100644 index 00000000..6229189b --- /dev/null +++ b/Src/tataki/export.h @@ -0,0 +1,33 @@ +#ifndef TATAKI_EXPORT_H +#define TATAKI_EXPORT_H + +#include <bfc/platform/types.h> +#include <api/service/api_service.h> + +#ifdef _WIN32 +#ifdef TATAKI_STATIC +#define TATAKIAPI +#else +#ifdef TATAKI_EXPORTS +#define TATAKIAPI __declspec(dllexport) +#else +#define TATAKIAPI __declspec(dllimport) +#endif +#endif +#elif defined(__GNUC__) +#ifdef TATAKI_EXPORTS +#define TATAKIAPI __attribute__ ((visibility("default"))) +#else +#define TATAKIAPI +#endif +#else +#error port me +#endif + +namespace Tataki +{ +extern "C" TATAKIAPI size_t Init(api_service *_serviceApi); +extern "C" TATAKIAPI size_t Quit(); +} + +#endif
\ No newline at end of file diff --git a/Src/tataki/main.cpp b/Src/tataki/main.cpp new file mode 100644 index 00000000..ed211aac --- /dev/null +++ b/Src/tataki/main.cpp @@ -0,0 +1,122 @@ +#include "api__tataki.h" +#include <api/service/waservicefactory.h> +#include <tataki/export.h> +#include <tataki/canvas/bltcanvas.h> +#include "../nu/ServiceWatcher.h" + +api_service *WASABI_API_SVC=0; +api_application *WASABI_API_APP=0; +api_syscb *WASABI_API_SYSCB=0; +api_font *WASABI_API_FONT=0; +wnd_api *WASABI_API_WND=0; +api_config *WASABI_API_CONFIG=0; +imgldr_api *WASABI_API_IMGLDR=0; +api_memmgr *WASABI_API_MEMMGR=0; +api_skin *WASABI_API_SKIN=0; +api_random *AGAVE_API_RANDOM=0; +api_palette *WASABI_API_PALETTE=0; +DWORD bitmap_cache_tls=TLS_OUT_OF_INDEXES; + +ServiceWatcher serviceWatcher; +template <class api_t> +api_t *GetService(GUID serviceGUID) +{ + waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(serviceGUID); + if (sf) + return reinterpret_cast<api_t *>( sf->getInterface() ); + else + return 0; + +} + +template <class api_t> +inline void ReleaseService(GUID serviceGUID, api_t *&service) +{ + if (service) + { + waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(serviceGUID); + if (sf) + sf->releaseInterface(service); + + service=0; + } +} + +static size_t refCount=0; +TATAKIAPI size_t Tataki::Init(api_service *_serviceApi) +{ + refCount++; + if (bitmap_cache_tls == TLS_OUT_OF_INDEXES) + bitmap_cache_tls=TlsAlloc(); + + if (!WASABI_API_SVC) + { + WASABI_API_SVC = _serviceApi; + WASABI_API_SYSCB = GetService<api_syscb>(syscbApiServiceGuid); + AGAVE_API_RANDOM = GetService<api_random>(randomApiGUID); + WASABI_API_PALETTE = GetService<api_palette>(PaletteManagerGUID); + + serviceWatcher.WatchWith(WASABI_API_SVC); + serviceWatcher.WatchFor(&WASABI_API_APP, applicationApiServiceGuid); + serviceWatcher.WatchFor(&WASABI_API_FONT, fontApiServiceGuid); + serviceWatcher.WatchFor(&WASABI_API_WND, wndApiServiceGuid); + serviceWatcher.WatchFor(&WASABI_API_CONFIG, configApiServiceGuid); + serviceWatcher.WatchFor(&WASABI_API_IMGLDR, imgLdrApiServiceGuid); + serviceWatcher.WatchFor(&WASABI_API_MEMMGR, memMgrApiServiceGuid); + serviceWatcher.WatchFor(&WASABI_API_SKIN, skinApiServiceGuid); + + // register for service callbacks in case any of these don't exist yet + WASABI_API_SYSCB->syscb_registerCallback(&serviceWatcher); + } + return refCount; +} + +TATAKIAPI size_t Tataki::Quit() +{ + if (!--refCount) + { + serviceWatcher.StopWatching(); + serviceWatcher.Clear(); + + ReleaseService(syscbApiServiceGuid, WASABI_API_SYSCB); + ReleaseService(applicationApiServiceGuid, WASABI_API_APP); + ReleaseService(fontApiServiceGuid,WASABI_API_FONT); + ReleaseService(wndApiServiceGuid, WASABI_API_WND); + ReleaseService(configApiServiceGuid, WASABI_API_CONFIG); + ReleaseService(imgLdrApiServiceGuid, WASABI_API_IMGLDR); + ReleaseService(memMgrApiServiceGuid, WASABI_API_MEMMGR); + ReleaseService(skinApiServiceGuid, WASABI_API_SKIN); + ReleaseService(randomApiGUID, AGAVE_API_RANDOM); + ReleaseService(PaletteManagerGUID, WASABI_API_PALETTE); + + // unregister callbacks + // release any services we have + WASABI_API_SVC = 0; + } + return refCount; +} + +extern "C" BOOL WINAPI DllMain( + HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved +) +{ + Wasabi::Std::Initialize(); + if (fdwReason == DLL_PROCESS_DETACH && bitmap_cache_tls!=TLS_OUT_OF_INDEXES) + { + TlsFree(bitmap_cache_tls); + bitmap_cache_tls=TLS_OUT_OF_INDEXES; + } + else if (fdwReason == DLL_THREAD_DETACH && bitmap_cache_tls!=TLS_OUT_OF_INDEXES) + { + BltCanvas *cache_canvas = (BltCanvas *)TlsGetValue(bitmap_cache_tls); + if (cache_canvas) + { + delete cache_canvas; + TlsSetValue(bitmap_cache_tls, 0); // this is probably unnecessary but just in case + } + + } + return TRUE; +} diff --git a/Src/tataki/region/api_region.cpp b/Src/tataki/region/api_region.cpp new file mode 100644 index 00000000..f9c263ef --- /dev/null +++ b/Src/tataki/region/api_region.cpp @@ -0,0 +1 @@ +#include "api_region.h"
\ No newline at end of file diff --git a/Src/tataki/region/api_region.h b/Src/tataki/region/api_region.h new file mode 100644 index 00000000..2dbcd51f --- /dev/null +++ b/Src/tataki/region/api_region.h @@ -0,0 +1,201 @@ +#ifndef __WASABI_API_REGION_H +#define __WASABI_API_REGION_H + +#include <bfc/dispatch.h> +#include <bfc/platform/export.h> + +class NOVTABLE api_region : public Dispatchable +{ +protected: + api_region() {} + virtual ~api_region() {} + +public: + DISPATCH_CODES + { + REGION_GETOSHANDLE = 50, + REGION_CLONE = 100, + REGION_DISPOSECLONE = 110, + REGION_PTINREGION = 120, + REGION_OFFSET = 130, + REGION_GETBOX = 140, + REGION_SUBTRACTRGN = 150, + REGION_SUBTRACTRECT = 160, + REGION_ADDRECT = 170, + REGION_ADD = 180, + REGION_AND = 190, + REGION_SETRECT = 200, + REGION_EMPTY = 210, + REGION_ISEMPTY = 220, + REGION_EQUALS = 230, + REGION_ENCLOSED = 240, + REGION_INTERSECTRGN = 250, + REGION_DOESINTERSECTRGN = 251, + REGION_INTERSECTRECT = 260, + REGION_ISRECT = 270, + REGION_SCALE = 280, + REGION_DEBUG = 290, + REGION_MAKEWNDREGION = 300, + REGION_GETNUMRECTS = 310, + REGION_ENUMRECT = 320, + }; +public: + OSREGIONHANDLE getOSHandle(); // avoid as much as you can, should be used only when you need to call the OS api + + 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 subtractRgn(const api_region *r) { subtractRegion(r); } //DEPRECATED + 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); +}; + +inline OSREGIONHANDLE api_region::getOSHandle() +{ + return _call(REGION_GETOSHANDLE, (OSREGIONHANDLE)NULL); +} + +inline api_region *api_region::clone() +{ + return _call(REGION_CLONE, (api_region *)NULL); +} + +inline void api_region::disposeClone(api_region *r) +{ + _voidcall(REGION_DISPOSECLONE, r); +} + +inline bool api_region::ptInRegion(const POINT *pt) +{ + return _call(REGION_PTINREGION, false, pt); +} + +inline void api_region::offset(int x, int y) +{ + _voidcall(REGION_OFFSET, x, y); +} + +inline void api_region::getBox(RECT *r) +{ + _voidcall(REGION_GETBOX, r); +} + +inline void api_region::subtractRegion(const api_region *reg) +{ + _voidcall(REGION_SUBTRACTRGN, reg); +} + +inline void api_region::subtractRect(const RECT *r) +{ + _voidcall(REGION_SUBTRACTRECT, r); +} + +inline void api_region::addRect(const RECT *r) +{ + _voidcall(REGION_ADDRECT, r); +} + +inline void api_region::addRegion(const api_region *r) +{ + _voidcall(REGION_ADD, r); +} + +inline void api_region::andRegion(const api_region *r) +{ + _voidcall(REGION_AND, r); +} + +inline void api_region::setRect(const RECT *r) +{ + _voidcall(REGION_SETRECT, r); +} + +inline void api_region::empty() +{ + _voidcall(REGION_EMPTY); +} + +inline int api_region::isEmpty() +{ + return _call(REGION_ISEMPTY, 0); +} + +inline int api_region::equals(const api_region *r) +{ + return _call(REGION_EQUALS, 0, r); +} + +inline int api_region::enclosed(const api_region *r, api_region *outside) +{ + return _call(REGION_ENCLOSED, 0, r, outside); +} + +inline int api_region::intersectRgn(const api_region *r, api_region *intersection) +{ + return _call(REGION_INTERSECTRGN, 0, r, intersection); +} + +inline int api_region::doesIntersectRgn(const api_region *r) +{ + return _call(REGION_DOESINTERSECTRGN, 0, r); +} + +inline int api_region::intersectRect(const RECT *r, api_region *intersection) +{ + return _call(REGION_INTERSECTRECT, 0, r, intersection); +} + +inline int api_region::isRect() +{ + return _call(REGION_ISRECT, 0); +} + +inline void api_region::scale(double sx, double sy, bool round) +{ + _voidcall(REGION_SCALE, sx, sy, round); +} + +inline void api_region::debug(int async) +{ + _voidcall(REGION_DEBUG, async); +} + +inline OSREGIONHANDLE api_region::makeWindowRegion() +{ + return _call(REGION_MAKEWNDREGION, (OSREGIONHANDLE)NULL); +} + +inline int api_region::getNumRects() +{ + return _call(REGION_GETNUMRECTS, 0); +} + +inline int api_region::enumRect(int n, RECT *r) +{ + return _call(REGION_ENUMRECT, 0, n, r); +} + +#endif diff --git a/Src/tataki/region/mac/osx_region_hishape.cpp b/Src/tataki/region/mac/osx_region_hishape.cpp new file mode 100644 index 00000000..348ba1de --- /dev/null +++ b/Src/tataki/region/mac/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/tataki/region/mac/region.h b/Src/tataki/region/mac/region.h new file mode 100644 index 00000000..f3404ea2 --- /dev/null +++ b/Src/tataki/region/mac/region.h @@ -0,0 +1,116 @@ +#ifndef __REGION_H +#define __REGION_H + +#include <tataki/export.h> +#include <Carbon/Carbon.h> +#include <bfc/platform/platform.h> +#include <tataki/region/api_region.h> + +class SkinBitmap; + +class TATAKIAPI 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 TATAKIAPI 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/tataki/region/region.h b/Src/tataki/region/region.h new file mode 100644 index 00000000..cf03c01c --- /dev/null +++ b/Src/tataki/region/region.h @@ -0,0 +1,5 @@ +#if defined _WIN64 || defined _WIN32 +#include "win/region.h" +#elif defined(__APPLE__) +#include "mac/region.h" +#endif diff --git a/Src/tataki/region/win/region.h b/Src/tataki/region/win/region.h new file mode 100644 index 00000000..849fba3e --- /dev/null +++ b/Src/tataki/region/win/region.h @@ -0,0 +1,137 @@ +#ifndef __REGION_H +#define __REGION_H + +#include <tataki/bitmap/bitmap.h> +#include <bfc/dispatch.h> +#include <tataki/export.h> + +class BaseWnd; +class Canvas; +class api_region; +class RegionServer; + +#include <tataki/region/api_region.h> + +class TATAKIAPI 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 TATAKIAPI 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/tataki/region/win/win32_region.cpp b/Src/tataki/region/win/win32_region.cpp new file mode 100644 index 00000000..5fb3c3c5 --- /dev/null +++ b/Src/tataki/region/win/win32_region.cpp @@ -0,0 +1,813 @@ +#if defined _WIN64 || defined _WIN32 +#include <tataki/api__tataki.h> +#include "region.h" +#include <api/imgldr/api_imgldr.h> +#include <tataki/region/api_region.h> +#include <tataki/canvas/ifc_canvas.h> +#include <api/wnd/basewnd.h> + + +#define GETOSHANDLE(x) (const_cast<api_region *>(x)->getOSHandle()) + +#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_EQUALS, equals); +CB(REGION_ENCLOSED, enclosed); +CB(REGION_INTERSECTRECT, intersectRect); +CB(REGION_DOESINTERSECTRGN, doesIntersectRgn); +CB(REGION_INTERSECTRGN, intersectRgn); +CB(REGION_ISRECT, isRect); +VCB(REGION_SCALE, scale); +VCB(REGION_DEBUG, debug); +CB(REGION_MAKEWNDREGION, makeWindowRegion); +CB(REGION_GETNUMRECTS, getNumRects); +CB(REGION_ENUMRECT, enumRect); +END_DISPATCH; +#undef CBCLASS + +#define CHECK_REGION \ + if (hrgn == NULL) hrgn = CreateRectRgn(0,0,0,0); + +RegionI::RegionI() +{ + hrgn = CreateRectRgn(0, 0, 0, 0); + init(); +} + +RegionI::RegionI(const RECT *r) +{ + hrgn = 0; + init(); + optrect = *r; + optimized = 1; + //hrgn = CreateRectRgn(r->left,r->top,r->right,r->bottom); + //if (!hrgn) hrgn = CreateRectRgn(0,0,0,0); + //init(); + //optimize(); +} + +RegionI::RegionI(int l, int t, int r, int b) +{ + hrgn = 0; + init(); + optrect.left = l; + optrect.top = t; + optrect.right = r; + optrect.bottom = b; + optimized = 1; + + //hrgn = CreateRectRgn(l,t,r,b); + //if (!hrgn) hrgn = CreateRectRgn(0,0,0,0); + //init(); + //optimize(); +} + +RegionI::RegionI(OSREGIONHANDLE r) +{ + OSREGIONHANDLE R = CreateRectRgn(0, 0, 0, 0); + CombineRgn(R, r, r, RGN_COPY); + hrgn = R; + init(); + optimize(); +} + +RegionI::RegionI(const RegionI *copy) +{ + init(); + if (copy->optimized) + { + optrect = copy->optrect; + optimized = copy->optimized; + hrgn = 0; + } + else + { + hrgn = CreateRectRgn(0, 0, 0, 0); + CombineRgn(hrgn, copy->hrgn, copy->hrgn, RGN_COPY); + } +} + +RegionI::RegionI(Canvas *c, RECT *defbounds) +{ + hrgn = CreateRectRgn(0, 0, 0, 0); + if (!GetClipRgn(c->getHDC(), hrgn)) + { + if (defbounds != NULL) + { + SetRectRgn(hrgn, defbounds->left, defbounds->top, defbounds->right, defbounds->bottom); + optrect=*defbounds; + optimized=1; + } + } + init(); + optimize(); +} + +RegionI::~RegionI() +{ + delete lastdebug; + if (srv != NULL) srv->delRef(this); + ASSERT(clonecount == 0); + if (srv == NULL && hrgn != NULL) DeleteObject(hrgn); +} + +void RegionI::init() +{ + srv = NULL; + clonecount = 0; + lastdebug = NULL; + optimized = 0; +} + +api_region *RegionI::clone() +{ + api_region *newregion = new RegionI(this); + clonecount++; + return newregion; +} + +void RegionI::disposeClone(api_region *r) +{ + RegionI *ri = static_cast<RegionI *>(r); + delete ri; // todo: validate pointer before deleting + clonecount--; +} + +// returns a handle that SetWindowRgn understands (non portable). We should NOT delete this handle, windows will delete +// it by itself upon setting a new region of destroying the window +OSREGIONHANDLE RegionI::makeWindowRegion() +{ + deoptimize(); + OSREGIONHANDLE R = CreateRectRgn(0, 0, 0, 0); + CombineRgn(R, hrgn, hrgn, RGN_COPY); + optimize(); + return R; +} + +RegionI::RegionI(SkinBitmap *bitmap, RECT *r, int xoffset, int yoffset, bool inverted, int dothreshold, char threshold, int thinverse, int minalpha) +{ + init(); + const wchar_t *id = bitmap->getBitmapName(); + + if (xoffset == 0 && yoffset == 0 && r == NULL && !inverted && !dothreshold && minalpha == 1 && id != NULL && *id != 0) + { + srv = WASABI_API_IMGLDR->imgldr_requestSkinRegion(id); + if (srv != NULL) + { + srv->addRef(this); + hrgn = srv->getRegion()->getOSHandle(); + } + } + + if (srv == NULL) + { + if (r) + hrgn = alphaToRegionRect(bitmap, xoffset, yoffset, TRUE, r->left, r->top, r->right - r->left, r->bottom - r->top, inverted, dothreshold, threshold, thinverse, minalpha); + else + hrgn = alphaToRegionRect(bitmap, xoffset, yoffset, FALSE, 0, 0, 0, 0, inverted, dothreshold, threshold, thinverse, minalpha); + + if (id != NULL && *id != 0) + { + if (xoffset == 0 && yoffset == 0 && r == NULL && !inverted && !dothreshold && minalpha == 1) + { + WASABI_API_IMGLDR->imgldr_cacheSkinRegion(id, this); + srv = WASABI_API_IMGLDR->imgldr_requestSkinRegion(id); + if (srv != NULL) + { + srv->addRef(this); + DeleteObject(hrgn); + hrgn = srv->getRegion()->getOSHandle(); + } + } + } + } + optimize(); + +} + +OSREGIONHANDLE RegionI::alphaToRegionRect(SkinBitmap *bitmap, int xoffset, int yoffset, bool portion, int _x, int _y, int _w, int _h, bool inverted, int dothreshold, unsigned char threshold, int thinverse, int minalpha) +{ + return alphaToRegionRect(bitmap->getBits(), bitmap->getX(), bitmap->getY(), bitmap->getWidth(), bitmap->getHeight(), bitmap->getFullWidth(), bitmap->getFullHeight(), xoffset, yoffset, portion, _x, _y, _w, _h, inverted, dothreshold, threshold, thinverse, minalpha); +} + +OSREGIONHANDLE RegionI::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 char threshold, int thinverse, int minalpha) +{ + OSREGIONHANDLE hRgn = NULL; + if (!pbits32) return NULL; + + RGNDATA *pData; + int y, x; + + // For better performances, we will use the ExtCreateRegion() function to create the + // region. This function take a RGNDATA structure on entry. We will add rectangles by + // amount of ALLOC_UNIT number in this structure. + // JF> rects are 8 bytes, so this allocates just under 16kb of memory, no need to REALLOC +#define MAXRECTS 2000 + __int8 regionMemory[sizeof(RGNDATAHEADER) + (sizeof(RECT) * MAXRECTS)] = {0}; + //pData = (RGNDATA *)MALLOC(sizeof(RGNDATAHEADER) + (sizeof(RECT) * MAXRECTS)); + pData = (RGNDATA *)regionMemory; + //if (!pData) return NULL; + + pData->rdh.dwSize = sizeof(RGNDATAHEADER); + pData->rdh.iType = RDH_RECTANGLES; + pData->rdh.nCount = pData->rdh.nRgnSize = 0; + + SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); + + int x_end = (portion ? _w + _x : bmWidth); + int y_end = (portion ? _h + _y : bmHeight); + int x_start = (portion ? _x : 0); + int y_start = (portion ? _y : 0); + + x_start += bmX; + x_end += bmX; + y_start += bmY; + y_end += bmY; + + unsigned int iv = minalpha << 24; //inverted?0xff000000:0; + + int shiftx = xoffset - bmX; + int shifty = yoffset - bmY; + + for (y = y_start; y < y_end; y++) + { + // Scan each bitmap pixel from left to right + unsigned int *lineptr = ((unsigned int *)pbits32) + fullw * y; + for (x = x_start; x < x_end; x++) + { + // Search for a continuous range of "non transparent pixels" + int x0 = x; + unsigned int *p = lineptr; + if (dothreshold) + { + if (inverted) + { + if (thinverse) + { + while (x < x_end) + { + unsigned int a = p[x]; + if ((a&0xff000000) >= iv || + (((((a & 0xFF) > threshold || ((a & 0xFF00) >> 8) > threshold || ((a & 0xFF0000) >> 16) > threshold))))) + break; + x++; + } + } + else + { + while (x < x_end) + { + unsigned int a = p[x]; + if ((a&0xff000000) >= iv || + (((((a & 0xFF) < threshold || ((a & 0xFF00) >> 8) < threshold || ((a & 0xFF0000) >> 16) < threshold))))) + break; + x++; + } + } + } + else + { + if (thinverse) + { + while (x < x_end) + { + unsigned int a = p[x]; + if ((a&0xff000000) < iv || + (((((a & 0xFF) > threshold || ((a & 0xFF00) >> 8) > threshold || ((a & 0xFF0000) >> 16) > threshold))))) + break; + x++; + } + } + else + { + while (x < x_end) + { + unsigned int a = p[x]; + if ((a&0xff000000) < iv || + (((((a & 0xFF) < threshold || ((a & 0xFF00) >> 8) < threshold || ((a & 0xFF0000) >> 16) < threshold))))) + break; + x++; + } + } + } + } + else + { + if (inverted) + { + while (x < x_end) + { + if ((p[x] & 0xFF000000) >= iv) break; + x++; + } + } + else + { + while (x < x_end) + { + if ((p[x] & 0xFF000000) < iv) break; + x++; + } + } + } + + if (x > x0) + { + SetRect(((RECT *)&pData->Buffer) + pData->rdh.nCount, x0 + shiftx, y + shifty, x + shiftx, y + 1 + shifty); + + pData->rdh.nCount++; + + if (x0 + shiftx < pData->rdh.rcBound.left) pData->rdh.rcBound.left = x0 + shiftx; + if (y + shifty < pData->rdh.rcBound.top) pData->rdh.rcBound.top = y + shifty; + if (x + shiftx > pData->rdh.rcBound.right) pData->rdh.rcBound.right = x + shiftx; + if (y + 1 + shifty > pData->rdh.rcBound.bottom) pData->rdh.rcBound.bottom = y + 1 + shifty; + + // On Windows98, ExtCreateRegion() may fail if the number of rectangles is too + // large (ie: > 4000). Therefore, we have to create the region by multiple steps. + if (pData->rdh.nCount == MAXRECTS) + { + OSREGIONHANDLE h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * pData->rdh.nCount), pData); + if (hRgn) + { + CombineRgn(hRgn, hRgn, h, RGN_OR); + DeleteObject(h); + } + else hRgn = h; + pData->rdh.nCount = 0; + SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); + } + } + } + } + + // Create or extend the region with the remaining rectangles + OSREGIONHANDLE h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * pData->rdh.nCount), pData); + if (hRgn) + { + CombineRgn(hRgn, hRgn, h, RGN_OR); + DeleteObject(h); + } + else + hRgn = h; + + // Clean up + //FREE(pData); + + return hRgn; +} + +bool RegionI::ptInRegion(const POINT *pt) +{ + if (optimized) return !!PtInRect(&optrect, *pt); + CHECK_REGION + return !!PtInRegion(hrgn, pt->x, pt->y); +} + +void RegionI::offset(int x, int y) +{ + if (optimized) + { + optrect.left += x; + optrect.top += y; + optrect.right += x; + optrect.bottom += y; + return ; + } + CHECK_REGION + if (srv) + { + hrgn = CreateRectRgn(0, 0, 0, 0); + RegionServer *s = srv; + srv = NULL; + addRegion(s->getRegion()); + s->delRef(this); + } + if (x == 0 && y == 0) return ; + deoptimize(); // because addregion may have optimized it + OffsetRgn(hrgn, x, y); + optimize(); +} + +void RegionI::getBox(RECT *r) +{ + if (optimized) + { + *r = optrect; + return ; + } + CHECK_REGION + GetRgnBox(hrgn, r); +} + +OSREGIONHANDLE RegionI::getOSHandle() +{ + deoptimize(); + CHECK_REGION + return hrgn; +} + +void RegionI::subtractRect(const RECT *r) +{ + RegionI s(r); + subtractRegion(&s); +} + +void RegionI::subtractRegion(const api_region *reg) +{ + if (srv) + { + hrgn = CreateRectRgn(0, 0, 0, 0); + RegionServer *s = srv; + srv = NULL; + addRegion(s->getRegion()); + s->delRef(this); + } + deoptimize(); + CombineRgn(hrgn, hrgn, GETOSHANDLE(reg), RGN_DIFF); + optimize(); +} + +void RegionI::andRegion(const api_region *reg) +{ + if (srv) + { + hrgn = CreateRectRgn(0, 0, 0, 0); + RegionServer *s = srv; + srv = NULL; + addRegion(s->getRegion()); + s->delRef(this); + } + + deoptimize(); + CombineRgn(hrgn, hrgn, GETOSHANDLE(reg), RGN_AND); + optimize(); +} + +void RegionI::addRect(const RECT *r) +{ + RegionI a(r); + addRegion(&a); +} + +void RegionI::addRegion(const api_region *reg) +{ + if (srv) + { + hrgn = CreateRectRgn(0, 0, 0, 0); + RegionServer *s = srv; + srv = NULL; + addRegion(s->getRegion()); + s->delRef(this); + } + deoptimize(); + ASSERT(reg != NULL); + CombineRgn(hrgn, hrgn, GETOSHANDLE(reg), RGN_OR); + optimize(); +} + +int RegionI::isEmpty() +{ + RECT r; + getBox(&r); + if (r.left == r.right || r.bottom == r.top) return 1; + return 0; +} + +int RegionI::enclosed(const api_region *r, api_region *outside) +{ + deoptimize(); + OSREGIONHANDLE del = NULL; + if (!outside) + del = CreateRectRgn(0, 0, 0, 0); + int rs = CombineRgn(outside ? outside->getOSHandle() : del, hrgn, GETOSHANDLE(r), RGN_DIFF); + if (del != NULL) DeleteObject(del); + optimize(); + return rs == NULLREGION; +} + +#define IntersectRgn(hrgnResult, hrgnA, hrgnB) CombineRgn(hrgnResult, hrgnA, hrgnB, RGN_AND) + +int RegionI::intersectRgn(const api_region *r, api_region *intersection) +{ + ASSERT(intersection != NULL); + ASSERT(intersection != this); + int rs; + if (optimized) + { + deoptimize(); + rs = IntersectRgn(intersection->getOSHandle(), hrgn, GETOSHANDLE(r)); + DeleteObject(hrgn); + hrgn=NULL; + optimized=1; + } + else + { + rs = IntersectRgn(intersection->getOSHandle(), hrgn, GETOSHANDLE(r)); + } + + return (rs != NULLREGION && rs != ERROR); +} + +int RegionI::doesIntersectRgn(const api_region *r) +{ + if (optimized) + { + return RectInRegion(GETOSHANDLE(r), &optrect); + } + else + { + CHECK_REGION + HRGN del = CreateRectRgn(0, 0, 0, 0); + int rs = IntersectRgn(del, hrgn, GETOSHANDLE(r)); + DeleteObject(del); + return (rs != NULLREGION && rs != ERROR); + } + +} + +int RegionI::intersectRect(const RECT *r, api_region *intersection) +{ + int rs; + ASSERT(intersection != NULL); + ASSERT(intersection != this); + if (optimized) + { + RECT temp = optrect; + rs = IntersectRect(&temp, &optrect, r); + intersection->setRect(&temp); + return rs; + } + else + { + CHECK_REGION + + OSREGIONHANDLE iRgn = intersection->getOSHandle(); + SetRectRgn(iRgn, r->left, r->top, r->right, r->bottom); + rs = IntersectRgn(iRgn, hrgn, iRgn); + } + return (rs != NULLREGION && rs != ERROR); +} + +int RegionI::doesIntersectRect(const RECT *r) +{ + return RectInRegion(hrgn, r); +} + +void RegionI::empty() +{ + if (srv) + { + hrgn = CreateRectRgn(0, 0, 0, 0); + ASSERT(hrgn != NULL); + srv->delRef(this); + srv = NULL; + optimize(); + return ; + } + //deoptimize(); + if (hrgn != NULL) + DeleteObject(hrgn); + hrgn=NULL; + //hrgn = CreateRectRgn(0, 0, 0, 0); + optrect.left=0; + optrect.top=0; + optrect.right=0; + optrect.bottom=0; + optimized=1; + //ASSERT(hrgn != NULL); + //optimize(); +} + +void RegionI::setRect(const RECT *r) +{ + if (srv) + { + hrgn = CreateRectRgnIndirect(r); + srv->delRef(this); + srv = NULL; + optimize(); + return ; + } + //deoptimize(); + //CHECK_REGION + if (hrgn) + DeleteObject(hrgn); + hrgn=NULL; + //SetRectRgn(hrgn, r->left, r->top, r->right, r->bottom); + optrect = *r; + optimized = 1; + //optimize(); +} + +int RegionI::equals(const api_region *r) +{ + ASSERT(r); + api_region *cl = const_cast<api_region*>(r)->clone(); + cl->subtractRegion(this); + int ret = cl->isEmpty(); + const_cast<api_region*>(r)->disposeClone(cl); + cl = clone(); + cl->subtractRegion(r); + ret &= cl->isEmpty(); + disposeClone(cl); + return ret; +} + +int RegionI::isRect() +{ + if (optimized) return 1; + RECT r; + getBox(&r); + RegionI n(&r); + return equals(&n); +} + +void RegionI::scale(double sx, double sy, bool round) +{ + if (srv) + { + hrgn = CreateRectRgn(0, 0, 0, 0); + RegionServer *s = srv; + srv = NULL; + addRegion(s->getRegion()); + s->delRef(this); + } + deoptimize(); + CHECK_REGION + DWORD size = 0; + RECT box; + getBox(&box); + size = GetRegionData(hrgn, size, NULL); + if (!size) return ; + RGNDATA *data = (RGNDATA *)MALLOC(size); + RECT *r = (RECT *)data->Buffer; + + GetRegionData(hrgn, size, (RGNDATA *)data); + double adj = round ? 0.99999 : 0.0; + int iadj = round ? 1 : 0; + + if (data->rdh.nCount == 1) + { + RECT nr = box; + nr.left = (int)((double)nr.left * sx - iadj); + nr.top = (int)((double)nr.top * sy - iadj); + nr.right = (int)((double)nr.right * sx + adj); + nr.bottom = (int)((double)nr.bottom * sy + adj); + setRect(&nr); + FREE(data); + return ; + } + + for (int i = 0;i < (int)data->rdh.nCount;i++) + { + r[i].left = (int)((double)r[i].left * sx - iadj); + r[i].top = (int)((double)r[i].top * sy - iadj); + r[i].right = (int)((double)r[i].right * sx + adj); + r[i].bottom = (int)((double)r[i].bottom * sy + adj); + } + + OSREGIONHANDLE nhrgn = ExtCreateRegion(NULL, size, data); + if (!nhrgn) + { + nhrgn = CreateRectRgn(0, 0, 0, 0); + } + FREE(data); + DeleteObject(hrgn); + hrgn = nhrgn; + optimize(); +} + +void RegionI::debug(int async) +{ + if (!async) + { + SysCanvas c; + RECT r; + getBox(&r); + // c.fillRect(&r, 0); + InvertRgn(c.getHDC(), getOSHandle()); + Sleep(200); + InvertRgn(c.getHDC(), getOSHandle()); + } + else + { + SysCanvas c; + RECT r; + getBox(&r); + // c.fillRect(&r, 0); + if (lastdebug) + InvertRgn(c.getHDC(), lastdebug->getOSHandle()); + delete lastdebug; + lastdebug = new RegionI(); + lastdebug->addRegion(this); + InvertRgn(c.getHDC(), getOSHandle()); + } +} + +// later we can cache this data or something if needed +int RegionI::getNumRects() +{ + if (optimized) return 1; + int bytes_needed = GetRegionData(hrgn, 0, NULL) + sizeof(RGNDATA); + MemBlock<unsigned char> data(bytes_needed); + GetRegionData(hrgn, bytes_needed, (LPRGNDATA)data.getMemory()); + RGNDATA *rgndata = reinterpret_cast<RGNDATA *>(data.getMemory()); + return rgndata->rdh.nCount; +} + +int RegionI::enumRect(int n, RECT *r) +{ + if (optimized) + { + if (n == 0) + { + if (r != NULL) *r = optrect; + return 1; + } + return 0; + } + if (n < 0) return 0; + int bytes_needed = GetRegionData(hrgn, 0, NULL) + sizeof(RGNDATA); + MemBlock<unsigned char> data(bytes_needed); + GetRegionData(hrgn, bytes_needed, (LPRGNDATA)data.getMemory()); + RGNDATA *rgndata = reinterpret_cast<RGNDATA *>(data.getMemory()); + int nrects = rgndata->rdh.nCount; + if (n >= nrects) return 0; + RECT *rectlist = reinterpret_cast<RECT*>(rgndata->Buffer); + *r = rectlist[n]; + return 1; +} + +void RegionI::optimize() +{ + if (optimized) return ; + if (srv != NULL) return ; // region is cached and shared, do not optimize + CHECK_REGION + getBox(&optrect); + + if (IsRectEmpty(&optrect)) + return; + + RECT br; + OSREGIONHANDLE gr = CreateRectRgnIndirect(&optrect); + OSREGIONHANDLE res = CreateRectRgn(0, 0, 0, 0); + +/* + // if they don't intersect, we may be offset + IntersectRgn(res, gr, hrgn); + GetRgnBox(res, &br); + if (br.left == br.right || br.bottom == br.top) + { + DeleteObject(gr); + DeleteObject(res); + return ; + } + */ + + // if they intersect, but when subtracting the region from the rect, we get nothing, they're the same, let's optimize + CombineRgn(res, gr, hrgn, RGN_DIFF); + DeleteObject(gr); + GetRgnBox(res, &br); + DeleteObject(res); + if (br.left == br.right || br.bottom == br.top) + { + optimized = 1; + DeleteObject(hrgn); + hrgn = NULL; + } +} + +void RegionI::deoptimize() +{ + if (!optimized) return ; + CHECK_REGION + SetRectRgn(hrgn, optrect.left, optrect.top, optrect.right, optrect.bottom); + //if (hrgn != NULL) { DeleteObject(hrgn); hrgn = NULL; } + //hrgn = CreateRectRgnIndirect(&optrect); + //CHECK_REGION + optimized = 0; +} + + +#define CBCLASS RegionServerI +START_DISPATCH; +VCB(REGIONSERVER_ADDREF, addRef); +VCB(REGIONSERVER_DELREF, delRef); +CB(REGIONSERVER_GETREGION, getRegion); +END_DISPATCH; + +#endif//WIN32 diff --git a/Src/tataki/resource.h b/Src/tataki/resource.h new file mode 100644 index 00000000..b6ce275a --- /dev/null +++ b/Src/tataki/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by tataki.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Src/tataki/tataki.rc b/Src/tataki/tataki.rc new file mode 100644 index 00000000..fcff7711 --- /dev/null +++ b/Src/tataki/tataki.rc @@ -0,0 +1,76 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""version.rc2""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "version.rc2" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Src/tataki/tataki.sln b/Src/tataki/tataki.sln new file mode 100644 index 00000000..62e79c42 --- /dev/null +++ b/Src/tataki/tataki.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tataki", "tataki.vcxproj", "{255B68B5-7EF8-45EF-A675-2D6B88147909}" + ProjectSection(ProjectDependencies) = postProject + {DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bfc", "..\Wasabi\bfc\bfc.vcxproj", "{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsutil", "..\nsutil\nsutil.vcxproj", "{DABE6307-F8DD-416D-9DAC-673E2DECB73F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|Win32.ActiveCfg = Debug|Win32 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|Win32.Build.0 = Debug|Win32 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|x64.ActiveCfg = Debug|x64 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|x64.Build.0 = Debug|x64 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|Win32.ActiveCfg = Release|Win32 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|Win32.Build.0 = Release|Win32 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|x64.ActiveCfg = Release|x64 + {255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|x64.Build.0 = Release|x64 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.ActiveCfg = Debug|Win32 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.Build.0 = Debug|Win32 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.ActiveCfg = Debug|x64 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.Build.0 = Debug|x64 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.ActiveCfg = Release|Win32 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.Build.0 = Release|Win32 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.ActiveCfg = Release|x64 + {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.Build.0 = Release|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.ActiveCfg = Debug|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.Build.0 = Debug|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.ActiveCfg = Debug|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.Build.0 = Debug|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.ActiveCfg = Release|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.Build.0 = Release|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.ActiveCfg = Release|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FC646532-2050-40A5-A2AB-F699F1C071C4} + EndGlobalSection +EndGlobal diff --git a/Src/tataki/tataki.vcxproj b/Src/tataki/tataki.vcxproj new file mode 100644 index 00000000..64cacbb4 --- /dev/null +++ b/Src/tataki/tataki.vcxproj @@ -0,0 +1,311 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{255B68B5-7EF8-45EF-A675-2D6B88147909}</ProjectGuid> + <RootNamespace>tataki</RootNamespace> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Label="Vcpkg"> + <VcpkgEnableManifest>false</VcpkgEnableManifest> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TATAKI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <BufferSecurityCheck>true</BufferSecurityCheck> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>nsutil.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <ImportLibrary>$(ProjectDir)x86_Debug\$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ +xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;TATAKI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <BufferSecurityCheck>true</BufferSecurityCheck> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>nsutil.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <ImportLibrary>$(ProjectDir)x64_Debug\$(ProjectName).lib</ImportLibrary> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ +xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>Full</Optimization> + <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> + <IntrinsicFunctions>true</IntrinsicFunctions> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>../Wasabi;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TATAKI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>nsutil.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>false</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <Optimization>Full</Optimization> + <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> + <IntrinsicFunctions>true</IntrinsicFunctions> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>../Wasabi;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;TATAKI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <DelayLoadDLLs>nsutil.dll;%(DelayLoadDLLs)</DelayLoadDLLs> + <GenerateDebugInformation>false</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + <PostBuildEvent> + <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command> + <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message> + </PostBuildEvent> + </ItemDefinitionGroup> + <ItemGroup> + <ProjectReference Include="..\nsutil\nsutil.vcxproj"> + <Project>{dabe6307-f8dd-416d-9dac-673e2decb73f}</Project> + </ProjectReference> + <ProjectReference Include="..\Wasabi\bfc\bfc.vcxproj"> + <Project>{d0ec862e-dddd-4f4f-934f-b75dc9062dc1}</Project> + <CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies> + <ReferenceOutputAssembly>true</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\Wasabi\Wasabi.vcxproj"> + <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\nu\ServiceWatcher.h" /> + <ClInclude Include="api__tataki.h" /> + <ClInclude Include="bitmap\autobitmap.h" /> + <ClInclude Include="bitmap\bitmap.h" /> + <ClInclude Include="bitmap\ifc_bitmap.h" /> + <ClInclude Include="bitmap\win\bitmap.h" /> + <ClInclude Include="blending\blending.h" /> + <ClInclude Include="canvas\bltcanvas.h" /> + <ClInclude Include="canvas\canvas.h" /> + <ClInclude Include="canvas\ifc_canvas.h" /> + <ClInclude Include="canvas\PaintCanvas.h" /> + <ClInclude Include="canvas\win\bltcanvas.h" /> + <ClInclude Include="canvas\win\canvas.h" /> + <ClInclude Include="color\filteredcolor.h" /> + <ClInclude Include="color\skinclr.h" /> + <ClInclude Include="export.h" /> + <ClInclude Include="region\api_region.h" /> + <ClInclude Include="region\region.h" /> + <ClInclude Include="region\win\region.h" /> + <ClInclude Include="resource.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\nu\ServiceWatcher.cpp" /> + <ClCompile Include="bitmap\autobitmap.cpp" /> + <ClCompile Include="bitmap\win\bitmap.cpp" /> + <ClCompile Include="blending\blending.cpp" /> + <ClCompile Include="canvas\ifc_canvas.cpp" /> + <ClCompile Include="canvas\win\BltCanvas.cpp" /> + <ClCompile Include="canvas\win\win32_canvas.cpp" /> + <ClCompile Include="color\filteredcolor.cpp" /> + <ClCompile Include="color\skinclr.cpp" /> + <ClCompile Include="main.cpp" /> + <ClCompile Include="region\api_region.cpp" /> + <ClCompile Include="region\win\win32_region.cpp" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="tataki.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/Src/tataki/tataki.vcxproj.filters b/Src/tataki/tataki.vcxproj.filters new file mode 100644 index 00000000..48d67814 --- /dev/null +++ b/Src/tataki/tataki.vcxproj.filters @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="region\win\win32_region.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="canvas\win\win32_canvas.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="color\skinclr.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\nu\ServiceWatcher.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="canvas\ifc_canvas.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="color\filteredcolor.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="canvas\win\BltCanvas.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="blending\blending.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bitmap\win\bitmap.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bitmap\autobitmap.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="region\api_region.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="api__tataki.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="region\api_region.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="bitmap\autobitmap.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="bitmap\win\bitmap.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="bitmap\bitmap.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="blending\blending.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="canvas\win\bltcanvas.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="canvas\bltcanvas.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="canvas\win\canvas.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="canvas\canvas.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="export.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="color\filteredcolor.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="bitmap\ifc_bitmap.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="canvas\ifc_canvas.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="canvas\PaintCanvas.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="region\win\region.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="region\region.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="resource.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\nu\ServiceWatcher.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="color\skinclr.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{f568eac1-1c90-440e-a7e4-961418304927}</UniqueIdentifier> + </Filter> + <Filter Include="Ressource Files"> + <UniqueIdentifier>{63948b0b-d98d-4579-bec2-570c5f1ac16d}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{e20af976-f354-4573-aa81-c23800d14d51}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="tataki.rc"> + <Filter>Ressource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Src/tataki/tataki.xcodeproj/project.pbxproj b/Src/tataki/tataki.xcodeproj/project.pbxproj new file mode 100644 index 00000000..4cd13955 --- /dev/null +++ b/Src/tataki/tataki.xcodeproj/project.pbxproj @@ -0,0 +1,418 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 0C2D18FA0C0BDD0B00ED9158 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D18F50C0BDD0B00ED9158 /* main.cpp */; }; + 0C2D18FB0C0BDD0B00ED9158 /* export.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D18F60C0BDD0B00ED9158 /* export.h */; }; + 0C2D18FC0C0BDD0B00ED9158 /* api.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D18F70C0BDD0B00ED9158 /* api.h */; }; + 0C2D192C0C0BDE7400ED9158 /* canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19220C0BDE7400ED9158 /* canvas.h */; }; + 0C2D192D0C0BDE7400ED9158 /* PaintCanvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19230C0BDE7400ED9158 /* PaintCanvas.h */; }; + 0C2D19300C0BDE7400ED9158 /* osx_canvas_layer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D19260C0BDE7400ED9158 /* osx_canvas_layer.cpp */; }; + 0C2D19310C0BDE7400ED9158 /* PaintCanvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D19270C0BDE7400ED9158 /* PaintCanvas.cpp */; }; + 0C2D19320C0BDE7400ED9158 /* osx_canvas_quartz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D19280C0BDE7400ED9158 /* osx_canvas_quartz.cpp */; }; + 0C2D19340C0BDE7400ED9158 /* bltcanvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D192A0C0BDE7400ED9158 /* bltcanvas.h */; }; + 0C2D193C0C0BDEB400ED9158 /* api_canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D19370C0BDEB400ED9158 /* api_canvas.cpp */; }; + 0C2D193D0C0BDEB400ED9158 /* canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19380C0BDEB400ED9158 /* canvas.h */; }; + 0C2D193E0C0BDEB400ED9158 /* PaintCanvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19390C0BDEB400ED9158 /* PaintCanvas.h */; }; + 0C2D193F0C0BDEB400ED9158 /* api_canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D193A0C0BDEB400ED9158 /* api_canvas.h */; }; + 0C2D19400C0BDEB400ED9158 /* bltcanvas.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D193B0C0BDEB400ED9158 /* bltcanvas.h */; }; + 0C2D194B0C0BDEFD00ED9158 /* ifc_bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19490C0BDEFD00ED9158 /* ifc_bitmap.h */; }; + 0C2D194C0C0BDEFD00ED9158 /* bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D194A0C0BDEFD00ED9158 /* bitmap.h */; }; + 0C2D19500C0BDFFF00ED9158 /* osx_bitmap_cgimage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D194E0C0BDFFF00ED9158 /* osx_bitmap_cgimage.cpp */; }; + 0C2D19510C0BDFFF00ED9158 /* osx_bitmap_cgimage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D194F0C0BDFFF00ED9158 /* osx_bitmap_cgimage.h */; }; + 0C2D19580C0BE06A00ED9158 /* region.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19550C0BE06A00ED9158 /* region.h */; }; + 0C2D19590C0BE06A00ED9158 /* api_region.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D19560C0BE06A00ED9158 /* api_region.h */; }; + 0C2D195A0C0BE06A00ED9158 /* api_region.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D19570C0BE06A00ED9158 /* api_region.cpp */; }; + 0C2D195F0C0BE08400ED9158 /* osx_region_hishape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D195D0C0BE08400ED9158 /* osx_region_hishape.cpp */; }; + 0C2D19600C0BE08400ED9158 /* region.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C2D195E0C0BE08400ED9158 /* region.h */; }; + 0CF66DD30CD5070800FF5DAF /* ServiceWatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CF66DD10CD5070800FF5DAF /* ServiceWatcher.cpp */; }; + 0CF66DD40CD5070800FF5DAF /* ServiceWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF66DD20CD5070800FF5DAF /* ServiceWatcher.h */; }; + 0CF66DE20CD507D000FF5DAF /* Vector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CF66DE10CD507D000FF5DAF /* Vector.h */; }; + 0CF66E990CD50E6C00FF5DAF /* libbfc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CF66E980CD50E6C00FF5DAF /* libbfc.a */; }; + 0CF66F5B0CD50E9800FF5DAF /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CF66F5A0CD50E9800FF5DAF /* Carbon.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0C2D19740C0BE0EA00ED9158 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0C2D19670C0BE0EA00ED9158 /* bfc.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D2AAC06F0554671400DB518D; + remoteInfo = bfc; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0C2D18F50C0BDD0B00ED9158 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; }; + 0C2D18F60C0BDD0B00ED9158 /* export.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = export.h; sourceTree = "<group>"; }; + 0C2D18F70C0BDD0B00ED9158 /* api.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = api.h; sourceTree = "<group>"; }; + 0C2D19220C0BDE7400ED9158 /* canvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = canvas.h; path = canvas/mac/canvas.h; sourceTree = "<group>"; }; + 0C2D19230C0BDE7400ED9158 /* PaintCanvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PaintCanvas.h; path = canvas/mac/PaintCanvas.h; sourceTree = "<group>"; }; + 0C2D19260C0BDE7400ED9158 /* osx_canvas_layer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = osx_canvas_layer.cpp; path = canvas/mac/osx_canvas_layer.cpp; sourceTree = "<group>"; }; + 0C2D19270C0BDE7400ED9158 /* PaintCanvas.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PaintCanvas.cpp; path = canvas/mac/PaintCanvas.cpp; sourceTree = "<group>"; }; + 0C2D19280C0BDE7400ED9158 /* osx_canvas_quartz.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = osx_canvas_quartz.cpp; path = canvas/mac/osx_canvas_quartz.cpp; sourceTree = "<group>"; }; + 0C2D192A0C0BDE7400ED9158 /* bltcanvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = bltcanvas.h; path = canvas/mac/bltcanvas.h; sourceTree = "<group>"; }; + 0C2D19370C0BDEB400ED9158 /* api_canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = api_canvas.cpp; path = canvas/api_canvas.cpp; sourceTree = "<group>"; }; + 0C2D19380C0BDEB400ED9158 /* canvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = canvas.h; path = canvas/canvas.h; sourceTree = "<group>"; }; + 0C2D19390C0BDEB400ED9158 /* PaintCanvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PaintCanvas.h; path = canvas/PaintCanvas.h; sourceTree = "<group>"; }; + 0C2D193A0C0BDEB400ED9158 /* api_canvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = api_canvas.h; path = canvas/api_canvas.h; sourceTree = "<group>"; }; + 0C2D193B0C0BDEB400ED9158 /* bltcanvas.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = bltcanvas.h; path = canvas/bltcanvas.h; sourceTree = "<group>"; }; + 0C2D19490C0BDEFD00ED9158 /* ifc_bitmap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ifc_bitmap.h; path = bitmap/ifc_bitmap.h; sourceTree = "<group>"; }; + 0C2D194A0C0BDEFD00ED9158 /* bitmap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = bitmap.h; path = bitmap/bitmap.h; sourceTree = "<group>"; }; + 0C2D194E0C0BDFFF00ED9158 /* osx_bitmap_cgimage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = osx_bitmap_cgimage.cpp; path = bitmap/mac/osx_bitmap_cgimage.cpp; sourceTree = "<group>"; }; + 0C2D194F0C0BDFFF00ED9158 /* osx_bitmap_cgimage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = osx_bitmap_cgimage.h; path = bitmap/mac/osx_bitmap_cgimage.h; sourceTree = "<group>"; }; + 0C2D19550C0BE06A00ED9158 /* region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = region.h; path = region/region.h; sourceTree = "<group>"; }; + 0C2D19560C0BE06A00ED9158 /* api_region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = api_region.h; path = region/api_region.h; sourceTree = "<group>"; }; + 0C2D19570C0BE06A00ED9158 /* api_region.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = api_region.cpp; path = region/api_region.cpp; sourceTree = "<group>"; }; + 0C2D195D0C0BE08400ED9158 /* osx_region_hishape.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = osx_region_hishape.cpp; path = region/mac/osx_region_hishape.cpp; sourceTree = "<group>"; }; + 0C2D195E0C0BE08400ED9158 /* region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = region.h; path = region/mac/region.h; sourceTree = "<group>"; }; + 0C2D19670C0BE0EA00ED9158 /* bfc.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = bfc.xcodeproj; path = ../Wasabi/bfc/bfc.xcodeproj; sourceTree = SOURCE_ROOT; }; + 0CF66DD10CD5070800FF5DAF /* ServiceWatcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ServiceWatcher.cpp; path = ../nu/ServiceWatcher.cpp; sourceTree = SOURCE_ROOT; }; + 0CF66DD20CD5070800FF5DAF /* ServiceWatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ServiceWatcher.h; path = ../nu/ServiceWatcher.h; sourceTree = SOURCE_ROOT; }; + 0CF66DE10CD507D000FF5DAF /* Vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Vector.h; path = ../nu/Vector.h; sourceTree = SOURCE_ROOT; }; + 0CF66E980CD50E6C00FF5DAF /* libbfc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbfc.a; path = ../Wasabi/bfc/build/Release/libbfc.a; sourceTree = SOURCE_ROOT; }; + 0CF66F5A0CD50E9800FF5DAF /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; }; + D2AAC0630554660B00DB518D /* libtataki.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libtataki.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D289988505E68E00004EDB86 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0CF66E990CD50E6C00FF5DAF /* libbfc.a in Frameworks */, + 0CF66F5B0CD50E9800FF5DAF /* Carbon.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* tataki */ = { + isa = PBXGroup; + children = ( + 0CF66F5A0CD50E9800FF5DAF /* Carbon.framework */, + 08FB7795FE84155DC02AAC07 /* Source */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = tataki; + sourceTree = "<group>"; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 0CF66E980CD50E6C00FF5DAF /* libbfc.a */, + 0CF66DE00CD5079C00FF5DAF /* nu */, + 0C2D19670C0BE0EA00ED9158 /* bfc.xcodeproj */, + 0C2D19540C0BE05D00ED9158 /* Region */, + 0C2D19480C0BDEEC00ED9158 /* Bitmap */, + 0C2D191E0C0BDE3300ED9158 /* Canvas */, + 0C2D18F50C0BDD0B00ED9158 /* main.cpp */, + 0C2D18F60C0BDD0B00ED9158 /* export.h */, + 0C2D18F70C0BDD0B00ED9158 /* api.h */, + ); + name = Source; + sourceTree = "<group>"; + }; + 0C2D191E0C0BDE3300ED9158 /* Canvas */ = { + isa = PBXGroup; + children = ( + 0C2D19370C0BDEB400ED9158 /* api_canvas.cpp */, + 0C2D19380C0BDEB400ED9158 /* canvas.h */, + 0C2D19390C0BDEB400ED9158 /* PaintCanvas.h */, + 0C2D193A0C0BDEB400ED9158 /* api_canvas.h */, + 0C2D193B0C0BDEB400ED9158 /* bltcanvas.h */, + 0C2D19360C0BDE7700ED9158 /* Mac */, + ); + name = Canvas; + sourceTree = "<group>"; + }; + 0C2D19360C0BDE7700ED9158 /* Mac */ = { + isa = PBXGroup; + children = ( + 0C2D19220C0BDE7400ED9158 /* canvas.h */, + 0C2D19230C0BDE7400ED9158 /* PaintCanvas.h */, + 0C2D19260C0BDE7400ED9158 /* osx_canvas_layer.cpp */, + 0C2D19270C0BDE7400ED9158 /* PaintCanvas.cpp */, + 0C2D19280C0BDE7400ED9158 /* osx_canvas_quartz.cpp */, + 0C2D192A0C0BDE7400ED9158 /* bltcanvas.h */, + ); + name = Mac; + sourceTree = "<group>"; + }; + 0C2D19480C0BDEEC00ED9158 /* Bitmap */ = { + isa = PBXGroup; + children = ( + 0C2D194D0C0BDFC200ED9158 /* Mac */, + 0C2D19490C0BDEFD00ED9158 /* ifc_bitmap.h */, + 0C2D194A0C0BDEFD00ED9158 /* bitmap.h */, + ); + name = Bitmap; + sourceTree = "<group>"; + }; + 0C2D194D0C0BDFC200ED9158 /* Mac */ = { + isa = PBXGroup; + children = ( + 0C2D194E0C0BDFFF00ED9158 /* osx_bitmap_cgimage.cpp */, + 0C2D194F0C0BDFFF00ED9158 /* osx_bitmap_cgimage.h */, + ); + name = Mac; + sourceTree = "<group>"; + }; + 0C2D19540C0BE05D00ED9158 /* Region */ = { + isa = PBXGroup; + children = ( + 0C2D195C0C0BE07400ED9158 /* Mac */, + 0C2D19550C0BE06A00ED9158 /* region.h */, + 0C2D19560C0BE06A00ED9158 /* api_region.h */, + 0C2D19570C0BE06A00ED9158 /* api_region.cpp */, + ); + name = Region; + sourceTree = "<group>"; + }; + 0C2D195C0C0BE07400ED9158 /* Mac */ = { + isa = PBXGroup; + children = ( + 0C2D195D0C0BE08400ED9158 /* osx_region_hishape.cpp */, + 0C2D195E0C0BE08400ED9158 /* region.h */, + ); + name = Mac; + sourceTree = "<group>"; + }; + 0C2D19680C0BE0EA00ED9158 /* Products */ = { + isa = PBXGroup; + children = ( + 0C2D19750C0BE0EA00ED9158 /* libbfc.a */, + ); + name = Products; + sourceTree = "<group>"; + }; + 0CF66DE00CD5079C00FF5DAF /* nu */ = { + isa = PBXGroup; + children = ( + 0CF66DE10CD507D000FF5DAF /* Vector.h */, + 0CF66DD10CD5070800FF5DAF /* ServiceWatcher.cpp */, + 0CF66DD20CD5070800FF5DAF /* ServiceWatcher.h */, + ); + name = nu; + sourceTree = "<group>"; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + D2AAC0630554660B00DB518D /* libtataki.dylib */, + ); + name = Products; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D2AAC0600554660B00DB518D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C2D18FB0C0BDD0B00ED9158 /* export.h in Headers */, + 0C2D18FC0C0BDD0B00ED9158 /* api.h in Headers */, + 0C2D192C0C0BDE7400ED9158 /* canvas.h in Headers */, + 0C2D192D0C0BDE7400ED9158 /* PaintCanvas.h in Headers */, + 0C2D19340C0BDE7400ED9158 /* bltcanvas.h in Headers */, + 0C2D193D0C0BDEB400ED9158 /* canvas.h in Headers */, + 0C2D193E0C0BDEB400ED9158 /* PaintCanvas.h in Headers */, + 0C2D193F0C0BDEB400ED9158 /* api_canvas.h in Headers */, + 0C2D19400C0BDEB400ED9158 /* bltcanvas.h in Headers */, + 0C2D194B0C0BDEFD00ED9158 /* ifc_bitmap.h in Headers */, + 0C2D194C0C0BDEFD00ED9158 /* bitmap.h in Headers */, + 0C2D19510C0BDFFF00ED9158 /* osx_bitmap_cgimage.h in Headers */, + 0C2D19580C0BE06A00ED9158 /* region.h in Headers */, + 0C2D19590C0BE06A00ED9158 /* api_region.h in Headers */, + 0C2D19600C0BE08400ED9158 /* region.h in Headers */, + 0CF66DD40CD5070800FF5DAF /* ServiceWatcher.h in Headers */, + 0CF66DE20CD507D000FF5DAF /* Vector.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D2AAC0620554660B00DB518D /* tataki */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "tataki" */; + buildPhases = ( + D2AAC0600554660B00DB518D /* Headers */, + D2AAC0610554660B00DB518D /* Sources */, + D289988505E68E00004EDB86 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tataki; + productName = tataki; + productReference = D2AAC0630554660B00DB518D /* libtataki.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "tataki" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* tataki */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 0C2D19680C0BE0EA00ED9158 /* Products */; + ProjectRef = 0C2D19670C0BE0EA00ED9158 /* bfc.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + D2AAC0620554660B00DB518D /* tataki */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 0C2D19750C0BE0EA00ED9158 /* libbfc.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libbfc.a; + remoteRef = 0C2D19740C0BE0EA00ED9158 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + D2AAC0610554660B00DB518D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C2D18FA0C0BDD0B00ED9158 /* main.cpp in Sources */, + 0C2D19300C0BDE7400ED9158 /* osx_canvas_layer.cpp in Sources */, + 0C2D19310C0BDE7400ED9158 /* PaintCanvas.cpp in Sources */, + 0C2D19320C0BDE7400ED9158 /* osx_canvas_quartz.cpp in Sources */, + 0C2D193C0C0BDEB400ED9158 /* api_canvas.cpp in Sources */, + 0C2D19500C0BDFFF00ED9158 /* osx_bitmap_cgimage.cpp in Sources */, + 0C2D195A0C0BE06A00ED9158 /* api_region.cpp in Sources */, + 0C2D195F0C0BE08400ED9158 /* osx_region_hishape.cpp in Sources */, + 0CF66DD30CD5070800FF5DAF /* ServiceWatcher.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB914B08733D8E0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + EXECUTABLE_PREFIX = lib; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/lib; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../Wasabi/bfc/build/Debug\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/../Wasabi/bfc/build/Release\""; + PRODUCT_NAME = tataki; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB914C08733D8E0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + EXECUTABLE_PREFIX = lib; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = TATAKI_EXPORTS; + INSTALL_PATH = /usr/local/lib; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/../Wasabi/bfc/build/Debug\""; + LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../Wasabi/bfc/build/Release\""; + PRODUCT_NAME = tataki; + }; + name = Release; + }; + 1DEB914F08733D8E0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_PREPROCESSOR_DEFINITIONS = TATAKI_EXPORTS; + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + .., + ../Wasabi, + ); + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Debug; + }; + 1DEB915008733D8E0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + GCC_MODEL_TUNING = ""; + GCC_PREPROCESSOR_DEFINITIONS = TATAKI_EXPORTS; + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + .., + ../Wasabi, + ); + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; + STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = dynamic; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "tataki" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB914B08733D8E0010E9CD /* Debug */, + 1DEB914C08733D8E0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "tataki" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB914F08733D8E0010E9CD /* Debug */, + 1DEB915008733D8E0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/Src/tataki/version.rc2 b/Src/tataki/version.rc2 new file mode 100644 index 00000000..8719eb33 --- /dev/null +++ b/Src/tataki/version.rc2 @@ -0,0 +1,39 @@ + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// +#include "../Winamp/buildType.h" +VS_VERSION_INFO VERSIONINFO + FILEVERSION WINAMP_PRODUCTVER + PRODUCTVERSION WINAMP_PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Winamp SA" + VALUE "FileDescription", "Winamp Support Library" + VALUE "FileVersion", STR_WINAMP_PRODUCTVER + VALUE "InternalName", "tataki.dll" + VALUE "LegalCopyright", "Copyright © 2005-2023 Winamp SA" + VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA" + VALUE "OriginalFilename", "tataki.dll" + VALUE "ProductName", "Winamp Shared Code Library" + VALUE "ProductVersion", STR_WINAMP_PRODUCTVER + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END |