aboutsummaryrefslogtreecommitdiff
path: root/Src/tataki/region/mac
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/tataki/region/mac
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/tataki/region/mac')
-rw-r--r--Src/tataki/region/mac/osx_region_hishape.cpp217
-rw-r--r--Src/tataki/region/mac/region.h116
2 files changed, 333 insertions, 0 deletions
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
+
+