123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813 |
- #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
|