DEADSOFTWARE

b53311e043688f0d54a3caa1d1a22553da232e22
[d2df-sdl.git] / src / flexui / fui_common.pas
1 (* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *)
17 {$INCLUDE ../shared/a_modes.inc}
18 unit fui_common;
20 interface
23 // ////////////////////////////////////////////////////////////////////////// //
24 type
25 TLaySize = record
26 public
27 w, h: Integer;
29 private
30 function getIdx (idx: Integer): Integer; inline;
31 procedure setIdx (idx, v: Integer); inline;
33 public
34 constructor Create (aw, ah: Integer);
36 function toString (): AnsiString;
38 function equals (constref a: TLaySize): Boolean; inline;
39 public
40 property item[idx: Integer]: Integer read getIdx write setIdx; default;
41 end;
43 TLayPos = record
44 public
45 x, y: Integer;
47 private
48 function getIdx (idx: Integer): Integer; inline;
49 procedure setIdx (idx, v: Integer); inline;
51 public
52 constructor Create (ax, ay: Integer);
54 function toString (): AnsiString;
56 function equals (constref a: TLayPos): Boolean; inline;
58 public
59 property item[idx: Integer]: Integer read getIdx write setIdx; default;
60 end;
62 TLayMargins = record
63 public
64 top, right, bottom, left: Integer;
66 public
67 constructor Create (atop, aright, abottom, aleft: Integer);
69 function toString (): AnsiString;
71 function horiz (): Integer; inline;
72 function vert (): Integer; inline;
73 end;
76 // ////////////////////////////////////////////////////////////////////////// //
77 type
78 TGxRGBA = packed record
79 public
80 r, g, b, a: Byte;
82 public
83 constructor Create (ar, ag, ab: Integer; aa: Integer=255);
85 function asUInt (): LongWord; inline;
86 function isOpaque (): Boolean; inline;
87 function isTransparent (): Boolean; inline;
89 function toString (): AnsiString;
91 // WARNING! This function does blending in RGB space, and RGB space is not linear!
92 // alpha value of `self` doesn't matter
93 // `aa` means: 255 for replace color, 0 for keep `self`
94 function blend (ar, ag, ab, aa: Integer): TGxRGBA; inline;
95 end;
97 TGxRect = packed record
98 public
99 x, y, w, h: Integer;
101 public
102 constructor Create (ax, ay, aw, ah: Integer);
104 function empty (): Boolean; inline; // invalid rects are empty too
105 function valid (): Boolean; inline;
107 function toString (): AnsiString;
109 // modifies this rect, so it won't be bigger than `r`
110 // returns `false` if this rect becomes empty
111 function intersect (constref r: TGxRect): Boolean; inline;
112 end;
114 TGxOfs = packed record
115 public
116 xofs, yofs: Integer;
118 public
119 constructor Create (axofs, ayofs: Integer);
120 end;
123 // ////////////////////////////////////////////////////////////////////////// //
124 // return `false` if destination rect is empty
125 // modifies rect0
126 function intersectRect (var x0, y0, w0, h0: Integer; const x1, y1, w1, h1: Integer): Boolean; inline;
127 procedure normRGBA (var r, g, b, a: Integer); inline;
130 implementation
132 uses
133 utils;
135 // ////////////////////////////////////////////////////////////////////////// //
136 constructor TLaySize.Create (aw, ah: Integer); begin w := aw; h := ah; end;
137 function TLaySize.getIdx (idx: Integer): Integer; inline; begin if (idx = 0) then result := w else if (idx = 1) then result := h else result := -1; end;
138 procedure TLaySize.setIdx (idx, v: Integer); inline; begin if (idx = 0) then w := v else if (idx = 1) then h := v; end;
139 function TLaySize.toString (): AnsiString; begin result := formatstrf('[%d,%d]', [w, h]); end;
140 function TLaySize.equals (constref a: TLaySize): Boolean; inline; begin result := (w = a.w) and (h = a.h); end;
142 constructor TLayPos.Create (ax, ay: Integer); begin x := ax; y := ay; end;
143 function TLayPos.getIdx (idx: Integer): Integer; inline; begin if (idx = 0) then result := x else if (idx = 1) then result := y else result := -1; end;
144 procedure TLayPos.setIdx (idx, v: Integer); inline; begin if (idx = 0) then x := v else if (idx = 1) then y := v; end;
145 function TLayPos.toString (): AnsiString; begin result := formatstrf('(%d,%d)', [x, y]); end;
146 function TLayPos.equals (constref a: TLayPos): Boolean; inline; begin result := (x = a.x) and (y = a.y); end;
148 constructor TLayMargins.Create (atop, aright, abottom, aleft: Integer);
149 begin
150 if (atop < 0) then atop := 0;
151 if (aright < 0) then aright := 0;
152 if (abottom < 0) then abottom := 0;
153 if (aleft < 0) then aleft := 0;
154 left := aleft;
155 right := aright;
156 top := atop;
157 bottom := abottom;
158 end;
159 function TLayMargins.toString (): AnsiString; begin result := formatstrf('(%s,%s,%s,%s)', [top, right, bottom, left]); end;
160 function TLayMargins.horiz (): Integer; inline; begin result := left+right; end;
161 function TLayMargins.vert (): Integer; inline; begin result := top+bottom; end;
164 // ////////////////////////////////////////////////////////////////////////// //
165 constructor TGxRGBA.Create (ar, ag, ab: Integer; aa: Integer=255);
166 begin
167 if (ar < 0) then r := 0 else if (ar > 255) then r := 255 else r := Byte(ar);
168 if (ag < 0) then g := 0 else if (ag > 255) then g := 255 else g := Byte(ag);
169 if (ab < 0) then b := 0 else if (ab > 255) then b := 255 else b := Byte(ab);
170 if (aa < 0) then a := 0 else if (aa > 255) then a := 255 else a := Byte(aa);
171 end;
173 function TGxRGBA.asUInt (): LongWord; inline; begin result := LongWord(r) or (LongWord(g) shl 8) or (LongWord(b) shl 16) or (LongWord(a) shl 24); end;
175 function TGxRGBA.isOpaque (): Boolean; inline; begin result := (a = 255); end;
176 function TGxRGBA.isTransparent (): Boolean; inline; begin result := (a = 0); end;
178 function TGxRGBA.blend (ar, ag, ab, aa: Integer): TGxRGBA; inline;
179 var
180 me, it, a_tmp_, dc_tmp_, srb_tmp_, sg_tmp_, drb_tmp_, dg_tmp_, orb_tmp_, og_tmp_: LongWord;
181 begin
182 if (aa <= 0) then begin result := self; exit; end;
183 result := TGxRGBA.Create(ar, ag, ab, aa);
184 if (aa >= 255) then begin result.a := a; exit; end;
185 me := asUInt;
186 it := result.asUInt;
187 a_tmp_ := (256-(255-(it shr 24))) and (-(1-(((255-(it shr 24))+1) shr 8))); // to not loose bits, but 255 should become 0
188 dc_tmp_ := me and $ffffff;
189 srb_tmp_ := (it and $ff00ff);
190 sg_tmp_ := (it and $00ff00);
191 drb_tmp_ := (dc_tmp_ and $ff00ff);
192 dg_tmp_ := (dc_tmp_ and $00ff00);
193 orb_tmp_ := (drb_tmp_+(((srb_tmp_-drb_tmp_)*a_tmp_+$800080) shr 8)) and $ff00ff;
194 og_tmp_ := (dg_tmp_+(((sg_tmp_-dg_tmp_)*a_tmp_+$008000) shr 8)) and $00ff00;
195 me := (orb_tmp_ or og_tmp_); // or $ff000000; /* and $ffffff;*/
196 result.r := Byte(me and $ff);
197 result.g := Byte((me shr 8) and $ff);
198 result.b := Byte((me shr 16) and $ff);
199 result.a := a;
200 end;
202 function TGxRGBA.toString (): AnsiString;
203 begin
204 if (a = 255) then result := formatstrf('rgb(%s,%s,%s)', [r, g, b])
205 else result := formatstrf('rgba(%s,%s,%s,%s)', [r, g, b, a]);
206 end;
209 // ////////////////////////////////////////////////////////////////////////// //
210 constructor TGxRect.Create (ax, ay, aw, ah: Integer); begin x := ax; y := ay; w := aw; h := ah; end;
212 function TGxRect.empty (): Boolean; inline; begin result := (w <= 0) or (h <= 0); end;
213 function TGxRect.valid (): Boolean; inline; begin result := (w < 0) or (h < 0); end;
215 function TGxRect.intersect (constref r: TGxRect): Boolean; inline;
216 begin
217 result := intersectRect(x, y, w, h, r.x, r.y, r.w, r.h);
218 end;
220 function TGxRect.toString (): AnsiString; begin result := formatstrf('(%s,%s;%sx%s)', [x, y, w, h]); end;
223 // ////////////////////////////////////////////////////////////////////////// //
224 constructor TGxOfs.Create (axofs, ayofs: Integer); begin xofs := axofs; yofs := ayofs; end;
227 // ////////////////////////////////////////////////////////////////////////// //
228 //TODO: overflow checks
229 function intersectRect (var x0, y0, w0, h0: Integer; const x1, y1, w1, h1: Integer): Boolean; inline;
230 var
231 ex0, ey0: Integer;
232 ex1, ey1: Integer;
233 begin
234 result := false;
235 if (w0 < 1) or (h0 < 1) or (w1 < 1) or (h1 < 1) then exit; // at least one rect is null
236 // check for intersection
237 ex0 := x0+w0;
238 ey0 := y0+h0;
239 ex1 := x1+w1;
240 ey1 := y1+h1;
241 if (ex0 <= x1) or (ey0 <= y1) or (ex1 <= x0) or (ey1 <= y0) then exit;
242 if (x0 >= ex1) or (y0 >= ey1) or (x1 >= ex0) or (y1 >= ey0) then exit;
243 // ok, intersects
244 if (x0 < x1) then x0 := x1;
245 if (y0 < y1) then y0 := y1;
246 if (ex0 > ex1) then ex0 := ex1;
247 if (ey0 > ey1) then ey0 := ey1;
248 w0 := ex0-x0;
249 h0 := ey0-y0;
250 result := (w0 > 0) and (h0 > 0);
251 end;
254 procedure normRGBA (var r, g, b, a: Integer); inline;
255 begin
256 if (a < 0) then a := 0 else if (a > 255) then a := 255;
257 if (r < 0) then r := 0 else if (r > 255) then r := 255;
258 if (g < 0) then g := 0 else if (g > 255) then g := 255;
259 if (b < 0) then b := 0 else if (b > 255) then b := 255;
260 end;
263 end.