2 * Pixel Graphics Library
3 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
4 * Understanding is not required. Only obedience.
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 3 of the License ONLY.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module iv
.sdpy
.rect
/*is aliced*/;
22 // ////////////////////////////////////////////////////////////////////////// //
25 int width
= -1; // <0: invalid rect
26 int height
= -1; // <0: invalid rect
28 string
toString () const @safe pure {
29 import std
.string
: format
;
30 return (valid ?
"(%s,%s)-(%s,%s)".format(x
, y
, x
+width
-1, y
+height
-1) : "(invalid-rect)");
34 // default constructor: (x, y, w, h)
35 this (int ax
, int ay
, int awidth
, int aheight
) { static if (__VERSION__
> 2067) pragma(inline
, true); set(ax
, ay
, awidth
, aheight
); }
37 @property pure const {
38 // note that killed rects are always equal
39 bool opEquals() (in auto ref Rect rc
) {
40 static if (__VERSION__
> 2067) pragma(inline
, true);
41 return (valid ?
(x0
== rc
.x0
&& y0
== rc
.y0
&& width
== rc
.width
&& height
== rc
.height
) : !rc
.valid
);
44 bool valid () { static if (__VERSION__
> 2067) pragma(inline
, true); return (width
>= 0 && height
>= 0); }
45 bool empty () { static if (__VERSION__
> 2067) pragma(inline
, true); return (width
<= 0 || height
<= 0); } // invalid rects are empty
47 int x0 () { static if (__VERSION__
> 2067) pragma(inline
, true); return x
; }
48 int y0 () { static if (__VERSION__
> 2067) pragma(inline
, true); return y
; }
49 int x1 () { static if (__VERSION__
> 2067) pragma(inline
, true); return (width
> 0 ? x
+width
-1 : x
-1); }
50 int y1 () { static if (__VERSION__
> 2067) pragma(inline
, true); return (height
> 0 ? y
+height
-1 : y
-1); }
54 void x0 (in int val
) { static if (__VERSION__
> 2067) pragma(inline
, true); width
= x
+width
-val
; x
= val
; }
55 void y0 (in int val
) { static if (__VERSION__
> 2067) pragma(inline
, true); height
= y
+height
-val
; y
= val
; }
56 void x1 (in int val
) { static if (__VERSION__
> 2067) pragma(inline
, true); width
= val
-x
+1; }
57 void y1 (in int val
) { static if (__VERSION__
> 2067) pragma(inline
, true); height
= val
-y
+1; }
60 void kill () { static if (__VERSION__
> 2067) pragma(inline
, true); width
= height
= -1; }
67 bool contains (in int ax
, in int ay
) const pure { static if (__VERSION__
> 2067) pragma(inline
, true); return (empty ?
false : (ax
>= x
&& ay
>= y
&& ax
< x
+width
&& ay
< y
+height
)); }
69 // is `this` contains `rc`?
70 bool contains() (in auto ref Rect rc
) const pure {
71 static if (__VERSION__
> 2067) pragma(inline
, true);
73 !this.empty
&& !rc
.empty
&&
74 rc
.x
>= this.x
&& rc
.y
>= this.y
&&
75 rc
.x1
<= this.x1
&& rc
.y1
<= this.y1
;
78 // is `this` inside `rc`?
79 bool inside() (in auto ref Rect rc
) const pure {
80 static if (__VERSION__
> 2067) pragma(inline
, true);
82 !rc
.empty
&& !this.empty
&&
83 this.x
>= rc
.x
&& this.y
>= rc
.y
&&
84 this.x1
<= rc
.x1
&& this.y1
<= rc
.y1
;
87 // is `r` and `this` overlaps?
88 bool overlap() (in auto ref Rect r
) const pure {
89 static if (__VERSION__
> 2067) pragma(inline
, true);
92 x
<= r
.x1
&& r
.x
<= x1
&& y
<= r
.y1
&& r
.y
<= y1
;
93 //!(x > r.x1 || r.x > x1 || y > r.y1 || r.y > y1);
96 // extend `this` so it will include `r`
97 void include() (in auto ref Rect r
) {
98 static if (__VERSION__
> 2067) pragma(inline
, true);
106 if (r
.x
< x
) x
= r
.x
;
107 if (r
.y
< y
) y
= r
.y
;
108 if (r
.x1
> x1
) x1
= r
.x1
;
109 if (r
.y1
> y1
) y1
= r
.y1
;
114 void set (int ax
, int ay
, int awidth
, int aheight
) {
115 static if (__VERSION__
> 2067) pragma(inline
, true);
122 void moveX0Y0By (int dx
, int dy
) {
123 static if (__VERSION__
> 2067) pragma(inline
, true);
130 void moveX1Y1By (int dx
, int dy
) {
131 static if (__VERSION__
> 2067) pragma(inline
, true);
136 void moveBy (int dx
, int dy
) {
137 static if (__VERSION__
> 2067) pragma(inline
, true);
143 * clip (x,y,len) stripe to this rect
146 * x = stripe start (not relative to rect)
147 * y = stripe start (not relative to rect)
148 * len = stripe length
153 * leftSkip = how much cells skipped at the left side
154 * result = false if stripe is completely clipped out
159 bool clipStripe (ref int x
, int y
, ref int len
, int* leftSkip
=null) @trusted {
161 if (leftSkip
is null) leftSkip
= &dummy
;
163 if (empty
) return false;
164 if (len
<= 0 || y
< this.y || y
>= this.y
+height || x
>= this.x
+width
) return false;
167 if (x
+len
<= this.x
) return false;
168 len
-= (*leftSkip
= this.x
-x
);
171 if (x
+len
>= this.x
+width
) {
173 len
= this.x
+width
-x
;
174 assert(len
> 0); // yeah, always
180 * clip this rect by another rect. both rects has same origin.
183 * rc = rect to clip by
186 * result = false if rect is completely clipped out (and is killed)
188 bool clipByRect() (in auto ref Rect rc
) {
189 // alas, dmd cannot inline function with more than one assignment
190 //static if (__VERSION__ > 2067) pragma(inline, true);
191 if (this.empty || rc
.empty ||
this.y1
< rc
.y0 ||
this.x1
< rc
.x0 ||
this.x0
> rc
.x1 ||
this.y0
> rc
.y1
) {
195 // this is at least partially inside rc rect
196 if (this.x0
< rc
.x0
) this.x0
= rc
.x0
; // clip left
197 if (this.y0
< rc
.y0
) this.y0
= rc
.y0
; // clip top
198 if (this.x1
> rc
.x1
) this.x1
= rc
.x1
; // clip right
199 if (this.y1
> rc
.y1
) this.y1
= rc
.y1
; // clip bottom
200 assert(!this.empty
); // yeah, always