egra: some agg mini optimisations (rendering, hittest)
[iv.d.git] / x11 / region.d
blobc7fad7ea70b65a3a90a7d12efdfd8d1b26e13208
1 module iv.x11.region /*is aliced*/;
3 import core.stdc.config;
5 import iv.alice;
6 import iv.x11.xlib : XPoint;
8 extern (C) @trusted nothrow @nogc:
11 struct XBoxRec {
12 short x1, x2, y1, y2;
14 alias XBox = XBoxRec*;
15 //alias BOX = Box;
16 //alias BoxRec = Box;
20 struct XRectangleRec {
21 short x, y, width, height;
23 alias XRegionRect = XRectangleRec*;
25 //alias RECTANGLE = Rectangle;
26 //alias RectangleRec = Rectangle;
27 //alias RectanglePtr = Rectangle*;
31 * clip region
33 struct XRegionRec {
34 c_long size;
35 c_long numRects;
36 XBox rects;
37 XBoxRec extents;
39 alias XRegion = XRegionRec*;
40 //alias REGION = XRegionRec;
43 //enum int TRUE = 1;
44 //enum int FALSE = 0;
45 private enum int MAXSHORT = 32767;
46 private enum int MINSHORT = -MAXSHORT;
49 private T MAX(T) (T a, T b) { return (a < b ? b : a); }
50 private T MIN(T) (T a, T b) { return (a > b ? b : a); }
53 /* 1 if two BOXs overlap.
54 * 0 if two BOXs do not overlap.
55 * Remember, x2 and y2 are not in the region
57 bool EXTENTCHECK (in XBox r1, in XBox r2) {
58 return
59 (r1.x2 > r2.x1) &&
60 (r1.x1 < r2.x2) &&
61 (r1.y2 > r2.y1) &&
62 (r1.y1 < r2.y2);
66 * update region extents
68 void EXTENTS (XBox r, XRegion idRect) {
69 if (r.x1 < idRect.extents.x1) idRect.extents.x1 = r.x1;
70 if (r.y1 < idRect.extents.y1) idRect.extents.y1 = r.y1;
71 if (r.x2 > idRect.extents.x2) idRect.extents.x2 = r.x2;
72 if (r.y2 > idRect.extents.y2) idRect.extents.y2 = r.y2;
76 * Check to see if there is enough memory in the present region.
78 bool MEMCHECK (XRegion reg, XBox rect, XBox firstrect) {
79 static void *Xrealloc (void *ptr, usize size) @trusted nothrow @nogc {
80 import core.stdc.stdlib : realloc;
81 return realloc(ptr, (size == 0 ? 1 : size));
84 bool result = false;
85 if (reg.numRects >= reg.size-1) {
86 firstrect = cast(XBox)Xrealloc(cast(void*)firstrect, cast(uint)(2*XBoxRec.sizeof*reg.size));
87 if (firstrect is null) {
88 result = false;
89 } else {
90 reg.size *= 2;
91 rect = &firstrect[reg.numRects];
92 result = true;
95 return result;
98 /* this routine checks to see if the previous rectangle is the same
99 * or subsumes the new rectangle to add.
101 bool CHECK_PREVIOUS (in XRegion Reg, in XBox R, short Rx1, short Ry1, short Rx2, short Ry2) {
102 return !(Reg.numRects > 0 && (R-1).y1 == Ry1 && (R-1).y2 == Ry2 && (R-1).x1 <= Rx1 && (R-1).x2 >= Rx2);
105 /* add a rectangle to the given Region */
106 void ADDRECT (XRegion reg, XBox r, short rx1, short ry1, short rx2, short ry2) {
107 if (rx1 < rx2 && ry1 < ry2 && CHECK_PREVIOUS(reg, r, rx1, ry1, rx2, ry2)) {
108 r.x1 = rx1;
109 r.y1 = ry1;
110 r.x2 = rx2;
111 r.y2 = ry2;
112 EXTENTS(r, reg);
113 ++reg.numRects;
114 ++r;
118 /* add a rectangle to the given Region */
119 void ADDRECTNOX (XRegion reg, XBox r, short rx1, short ry1, short rx2, short ry2) {
120 if (rx1 < rx2 && ry1 < ry2 && CHECK_PREVIOUS(reg, r, rx1, ry1, rx2, ry2)) {
121 r.x1 = rx1;
122 r.y1 = ry1;
123 r.x2 = rx2;
124 r.y2 = ry2;
125 ++reg.numRects;
126 ++r;
130 void EMPTY_REGION (XRegion pReg) {
131 pReg.numRects = 0;
134 c_long REGION_NOT_EMPTY (in XRegion pReg) {
135 return pReg.numRects;
138 bool INBOX (in XBox r, short x, short y) {
139 return (r.x2 > x && r.x1 <= x && r.y2 > y && r.y1 <= y);
143 * number of points to buffer before sending them off
144 * to scanlines() : Must be an even number
146 enum int NUMPTSTOBUFFER = 200;
149 * used to allocate buffers for points and link
150 * the buffers together
152 struct POINTBLOCK {
153 XPoint[NUMPTSTOBUFFER] pts;
154 POINTBLOCK* next;