DEADSOFTWARE

FlexUI: module renamings; moved standalone sdl carcass augemntation to FlexUI
[d2df-sdl.git] / src / flexui / fui_gfx_gl.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_gfx_gl;
20 interface
22 uses
23 SysUtils, Classes,
24 GL, GLExt, SDL2,
25 sdlcarcass,
26 fui_common, fui_events;
29 // ////////////////////////////////////////////////////////////////////////// //
30 // setup 2D OpenGL mode; will be called automatically in `glInit()`
31 procedure oglSetup2D (winWidth, winHeight: Integer; upsideDown: Boolean=false);
33 // the following calls MUST be paired AT ALL COSTS!
34 procedure gxBeginUIDraw (scale: Single=1.0);
35 procedure gxEndUIDraw ();
38 type
39 TScissorSave = record
40 public
41 wassc: Boolean;
42 scxywh: packed array[0..3] of GLint;
44 public
46 public
47 procedure save (enableScissoring: Boolean);
48 procedure restore ();
50 // set new scissor rect, bounded by the saved scissor rect
51 procedure combineRect (x, y, w, h: Integer);
52 end;
55 procedure oglDrawCursor ();
56 procedure oglDrawCursorAt (msX, msY: Integer);
58 function setupGLColor (r, g, b, a: Integer): Boolean;
59 function setupGLColor (constref clr: TGxRGBA): Boolean;
60 function isScaled (): Boolean;
62 function textWidth6 (const s: AnsiString): Integer;
63 function textWidth8 (const s: AnsiString): Integer;
64 // return width (including last empty pixel)
65 function drawTextInternal (wdt, x, y: Integer; const s: AnsiString; constref clr: TGxRGBA; tid: GLuint; constref fontwdt: array of Byte; prop: Boolean): Integer;
66 procedure drawLine (x1, y1, x2, y2: Integer; constref clr: TGxRGBA);
67 procedure drawVLine (x, y, len: Integer; constref clr: TGxRGBA);
68 procedure drawHLine (x, y, len: Integer; constref clr: TGxRGBA);
69 procedure drawRect (x, y, w, h: Integer; constref clr: TGxRGBA);
70 procedure drawRectUI (x, y, w, h: Integer; constref clr: TGxRGBA);
71 procedure darkenRect (x, y, w, h: Integer; a: Integer);
72 procedure fillRect (x, y, w, h: Integer; constref clr: TGxRGBA);
73 function drawText6 (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
74 function drawText8 (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
75 function drawText6Prop (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
76 function drawText8Prop (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
77 // x-centered at `x`
78 function drawText6XC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
79 function drawText8XC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
80 function drawText6PropXC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
81 function drawText8PropXC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
84 // ////////////////////////////////////////////////////////////////////////// //
85 var
86 gGfxDoClear: Boolean = true;
89 implementation
92 // ////////////////////////////////////////////////////////////////////////// //
93 procedure oglSetup2D (winWidth, winHeight: Integer; upsideDown: Boolean=false);
94 begin
95 glViewport(0, 0, winWidth, winHeight);
97 glDisable(GL_BLEND);
98 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
99 glDisable(GL_LINE_SMOOTH);
100 glDisable(GL_POINT_SMOOTH);
101 glDisable(GL_DEPTH_TEST);
102 glDisable(GL_TEXTURE_2D);
103 glDisable(GL_LIGHTING);
104 glDisable(GL_DITHER);
105 glDisable(GL_STENCIL_TEST);
106 glDisable(GL_SCISSOR_TEST);
107 glDisable(GL_CULL_FACE);
109 glMatrixMode(GL_PROJECTION);
110 glLoadIdentity();
111 if (upsideDown) then
112 begin
113 glOrtho(0, winWidth, 0, winHeight, -1, 1); // set origin to bottom left
114 end
115 else
116 begin
117 glOrtho(0, winWidth, winHeight, 0, -1, 1); // set origin to top left
118 end;
120 glMatrixMode(GL_MODELVIEW);
121 glLoadIdentity();
123 glClearColor(0, 0, 0, 0);
124 glColor4f(1, 1, 1, 1);
125 end;
128 procedure gxBeginUIDraw (scale: Single=1.0);
129 begin
130 glMatrixMode(GL_MODELVIEW);
131 glPushMatrix();
132 glLoadIdentity();
133 glScalef(scale, scale, 1);
134 end;
136 procedure gxEndUIDraw ();
137 begin
138 glMatrixMode(GL_MODELVIEW);
139 glPopMatrix();
140 end;
143 // ////////////////////////////////////////////////////////////////////////// //
144 // cursor (hi, Death Track!)
145 const curTexWidth = 32;
146 const curTexHeight = 32;
147 const curWidth = 17;
148 const curHeight = 23;
150 const cursorImg: array[0..curWidth*curHeight-1] of Byte = (
151 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
152 3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
153 3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
154 3,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
155 3,3,4,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
156 3,3,4,4,2,2,0,0,0,0,0,0,0,0,0,0,0,
157 3,3,4,4,4,2,2,0,0,0,0,0,0,0,0,0,0,
158 3,3,4,4,4,4,2,2,0,0,0,0,0,0,0,0,0,
159 3,3,4,4,4,5,6,2,2,0,0,0,0,0,0,0,0,
160 3,3,4,4,5,6,7,5,2,2,0,0,0,0,0,0,0,
161 3,3,4,5,6,7,5,4,5,2,2,0,0,0,0,0,0,
162 3,3,5,6,7,5,4,5,6,7,2,2,0,0,0,0,0,
163 3,3,6,7,5,4,5,6,7,7,7,2,2,0,0,0,0,
164 3,3,7,5,4,5,6,7,7,7,7,7,2,2,0,0,0,
165 3,3,5,4,5,6,8,8,8,8,8,8,8,8,2,0,0,
166 3,3,4,5,6,3,8,8,8,8,8,8,8,8,8,0,0,
167 3,3,5,6,3,3,0,0,0,0,0,0,0,0,0,0,0,
168 3,3,6,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
169 3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,
170 3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
171 3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
172 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
173 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
174 );
175 const cursorPal: array[0..9*4-1] of Byte = (
176 0, 0, 0, 0,
177 0, 0, 0,163,
178 85,255,255,255,
179 85, 85,255,255,
180 255, 85, 85,255,
181 170, 0,170,255,
182 85, 85, 85,255,
183 0, 0, 0,255,
184 0, 0,170,255
185 );
188 var
189 curtexid: GLuint = 0;
191 procedure createCursorTexture ();
192 var
193 tex, tpp: PByte;
194 c: Integer;
195 x, y: Integer;
196 begin
197 if (curtexid <> 0) then exit; //begin glDeleteTextures(1, @curtexid); curtexid := 0; end;
199 GetMem(tex, curTexWidth*curTexHeight*4);
200 try
201 FillChar(tex^, curTexWidth*curTexHeight*4, 0);
203 // draw shadow
204 for y := 0 to curHeight-1 do
205 begin
206 for x := 0 to curWidth-1 do
207 begin
208 if (cursorImg[y*curWidth+x] <> 0) then
209 begin
210 c := 1*4;
211 tpp := tex+((y+1)*(curTexWidth*4)+(x+3)*4);
212 tpp^ := cursorPal[c+0]; Inc(tpp);
213 tpp^ := cursorPal[c+1]; Inc(tpp);
214 tpp^ := cursorPal[c+2]; Inc(tpp);
215 tpp^ := cursorPal[c+3]; Inc(tpp);
216 tpp^ := cursorPal[c+0]; Inc(tpp);
217 tpp^ := cursorPal[c+1]; Inc(tpp);
218 tpp^ := cursorPal[c+2]; Inc(tpp);
219 tpp^ := cursorPal[c+3]; Inc(tpp);
220 end;
221 end;
222 end;
224 // draw cursor
225 for y := 0 to curHeight-1 do
226 begin
227 for x := 0 to curWidth-1 do
228 begin
229 c := cursorImg[y*curWidth+x]*4;
230 if (c <> 0) then
231 begin
232 tpp := tex+(y*(curTexWidth*4)+x*4);
233 tpp^ := cursorPal[c+0]; Inc(tpp);
234 tpp^ := cursorPal[c+1]; Inc(tpp);
235 tpp^ := cursorPal[c+2]; Inc(tpp);
236 tpp^ := cursorPal[c+3]; Inc(tpp);
237 end;
238 end;
239 end;
241 glGenTextures(1, @curtexid);
242 if (curtexid = 0) then raise Exception.Create('can''t create cursor texture');
244 glBindTexture(GL_TEXTURE_2D, curtexid);
245 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
246 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
250 //GLfloat[4] bclr = 0.0;
251 //glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bclr.ptr);
253 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, curTexWidth, curTexHeight, 0, GL_RGBA{gltt}, GL_UNSIGNED_BYTE, tex);
254 glFlush();
255 finally
256 FreeMem(tex);
257 end;
258 end;
260 procedure oglDrawCursorAt (msX, msY: Integer);
261 begin
262 //if (curtexid = 0) then createCursorTexture() else glBindTexture(GL_TEXTURE_2D, curtexid);
263 glBindTexture(GL_TEXTURE_2D, curtexid);
264 // blend it
265 glEnable(GL_BLEND);
266 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
267 glEnable(GL_TEXTURE_2D);
268 glDisable(GL_STENCIL_TEST);
269 glDisable(GL_SCISSOR_TEST);
270 glDisable(GL_LIGHTING);
271 glDisable(GL_DEPTH_TEST);
272 glDisable(GL_CULL_FACE);
273 // color and opacity
274 glColor4f(1, 1, 1, 0.9);
275 //Dec(msX, 2);
276 glBegin(GL_QUADS);
277 glTexCoord2f(0.0, 0.0); glVertex2i(msX, msY); // top-left
278 glTexCoord2f(1.0, 0.0); glVertex2i(msX+curTexWidth, msY); // top-right
279 glTexCoord2f(1.0, 1.0); glVertex2i(msX+curTexWidth, msY+curTexHeight); // bottom-right
280 glTexCoord2f(0.0, 1.0); glVertex2i(msX, msY+curTexHeight); // bottom-left
281 glEnd();
282 //Inc(msX, 2);
283 glDisable(GL_BLEND);
284 glDisable(GL_TEXTURE_2D);
285 glColor4f(1, 1, 1, 1);
286 glBindTexture(GL_TEXTURE_2D, 0);
287 end;
289 procedure oglDrawCursor (); begin oglDrawCursorAt(fuiMouseX, fuiMouseY); end;
292 // ////////////////////////////////////////////////////////////////////////// //
293 // fonts
294 const kgiFont6: array[0..256*8-1] of Byte = (
295 $00,$00,$00,$00,$00,$00,$00,$00,$3c,$42,$a5,$81,$a5,$99,$42,$3c,$3c,$7e,$db,$ff,$ff,$db,$66,$3c,$6c,$fe,
296 $fe,$fe,$7c,$38,$10,$00,$10,$38,$7c,$fe,$7c,$38,$10,$00,$10,$38,$54,$fe,$54,$10,$38,$00,$10,$38,$7c,$fe,
297 $fe,$10,$38,$00,$00,$00,$00,$30,$30,$00,$00,$00,$ff,$ff,$ff,$e7,$e7,$ff,$ff,$ff,$38,$44,$82,$82,$82,$44,
298 $38,$00,$c7,$bb,$7d,$7d,$7d,$bb,$c7,$ff,$0f,$03,$05,$79,$88,$88,$88,$70,$38,$44,$44,$44,$38,$10,$7c,$10,
299 $30,$28,$24,$24,$28,$20,$e0,$c0,$3c,$24,$3c,$24,$24,$e4,$dc,$18,$10,$54,$38,$ee,$38,$54,$10,$00,$10,$10,
300 $10,$7c,$10,$10,$10,$10,$10,$10,$10,$ff,$00,$00,$00,$00,$00,$00,$00,$ff,$10,$10,$10,$10,$10,$10,$10,$f0,
301 $10,$10,$10,$10,$10,$10,$10,$1f,$10,$10,$10,$10,$10,$10,$10,$ff,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,
302 $10,$10,$00,$00,$00,$ff,$00,$00,$00,$00,$00,$00,$00,$1f,$10,$10,$10,$10,$00,$00,$00,$f0,$10,$10,$10,$10,
303 $10,$10,$10,$1f,$00,$00,$00,$00,$10,$10,$10,$f0,$00,$00,$00,$00,$81,$42,$24,$18,$18,$24,$42,$81,$01,$02,
304 $04,$08,$10,$20,$40,$80,$80,$40,$20,$10,$08,$04,$02,$01,$00,$10,$10,$ff,$10,$10,$00,$00,$00,$00,$00,$00,
305 $00,$00,$00,$00,$20,$20,$20,$20,$00,$00,$20,$00,$50,$50,$50,$00,$00,$00,$00,$00,$50,$50,$f8,$50,$f8,$50,
306 $50,$00,$20,$78,$a0,$70,$28,$f0,$20,$00,$c0,$c8,$10,$20,$40,$98,$18,$00,$40,$a0,$40,$a8,$90,$98,$60,$00,
307 $10,$20,$40,$00,$00,$00,$00,$00,$10,$20,$40,$40,$40,$20,$10,$00,$40,$20,$10,$10,$10,$20,$40,$00,$88,$50,
308 $20,$f8,$20,$50,$88,$00,$00,$20,$20,$f8,$20,$20,$00,$00,$00,$00,$00,$00,$00,$20,$20,$40,$00,$00,$00,$78,
309 $00,$00,$00,$00,$00,$00,$00,$00,$00,$60,$60,$00,$00,$00,$08,$10,$20,$40,$80,$00,$70,$88,$98,$a8,$c8,$88,
310 $70,$00,$20,$60,$a0,$20,$20,$20,$f8,$00,$70,$88,$08,$10,$60,$80,$f8,$00,$70,$88,$08,$30,$08,$88,$70,$00,
311 $10,$30,$50,$90,$f8,$10,$10,$00,$f8,$80,$e0,$10,$08,$10,$e0,$00,$30,$40,$80,$f0,$88,$88,$70,$00,$f8,$88,
312 $10,$20,$20,$20,$20,$00,$70,$88,$88,$70,$88,$88,$70,$00,$70,$88,$88,$78,$08,$10,$60,$00,$00,$00,$20,$00,
313 $00,$20,$00,$00,$00,$00,$20,$00,$00,$20,$20,$40,$18,$30,$60,$c0,$60,$30,$18,$00,$00,$00,$f8,$00,$f8,$00,
314 $00,$00,$c0,$60,$30,$18,$30,$60,$c0,$00,$70,$88,$08,$10,$20,$00,$20,$00,$70,$88,$08,$68,$a8,$a8,$70,$00,
315 $20,$50,$88,$88,$f8,$88,$88,$00,$f0,$48,$48,$70,$48,$48,$f0,$00,$30,$48,$80,$80,$80,$48,$30,$00,$e0,$50,
316 $48,$48,$48,$50,$e0,$00,$f8,$80,$80,$f0,$80,$80,$f8,$00,$f8,$80,$80,$f0,$80,$80,$80,$00,$70,$88,$80,$b8,
317 $88,$88,$70,$00,$88,$88,$88,$f8,$88,$88,$88,$00,$70,$20,$20,$20,$20,$20,$70,$00,$38,$10,$10,$10,$90,$90,
318 $60,$00,$88,$90,$a0,$c0,$a0,$90,$88,$00,$80,$80,$80,$80,$80,$80,$f8,$00,$88,$d8,$a8,$a8,$88,$88,$88,$00,
319 $88,$c8,$c8,$a8,$98,$98,$88,$00,$70,$88,$88,$88,$88,$88,$70,$00,$f0,$88,$88,$f0,$80,$80,$80,$00,$70,$88,
320 $88,$88,$a8,$90,$68,$00,$f0,$88,$88,$f0,$a0,$90,$88,$00,$70,$88,$80,$70,$08,$88,$70,$00,$f8,$20,$20,$20,
321 $20,$20,$20,$00,$88,$88,$88,$88,$88,$88,$70,$00,$88,$88,$88,$88,$50,$50,$20,$00,$88,$88,$88,$a8,$a8,$d8,
322 $88,$00,$88,$88,$50,$20,$50,$88,$88,$00,$88,$88,$88,$70,$20,$20,$20,$00,$f8,$08,$10,$20,$40,$80,$f8,$00,
323 $70,$40,$40,$40,$40,$40,$70,$00,$00,$00,$80,$40,$20,$10,$08,$00,$70,$10,$10,$10,$10,$10,$70,$00,$20,$50,
324 $88,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$f8,$00,$40,$20,$10,$00,$00,$00,$00,$00,$00,$00,$70,$08,
325 $78,$88,$78,$00,$80,$80,$b0,$c8,$88,$c8,$b0,$00,$00,$00,$70,$88,$80,$88,$70,$00,$08,$08,$68,$98,$88,$98,
326 $68,$00,$00,$00,$70,$88,$f8,$80,$70,$00,$10,$28,$20,$f8,$20,$20,$20,$00,$00,$00,$68,$98,$98,$68,$08,$70,
327 $80,$80,$f0,$88,$88,$88,$88,$00,$20,$00,$60,$20,$20,$20,$70,$00,$10,$00,$30,$10,$10,$10,$90,$60,$40,$40,
328 $48,$50,$60,$50,$48,$00,$60,$20,$20,$20,$20,$20,$70,$00,$00,$00,$d0,$a8,$a8,$a8,$a8,$00,$00,$00,$b0,$c8,
329 $88,$88,$88,$00,$00,$00,$70,$88,$88,$88,$70,$00,$00,$00,$b0,$c8,$c8,$b0,$80,$80,$00,$00,$68,$98,$98,$68,
330 $08,$08,$00,$00,$b0,$c8,$80,$80,$80,$00,$00,$00,$78,$80,$f0,$08,$f0,$00,$40,$40,$f0,$40,$40,$48,$30,$00,
331 $00,$00,$90,$90,$90,$90,$68,$00,$00,$00,$88,$88,$88,$50,$20,$00,$00,$00,$88,$a8,$a8,$a8,$50,$00,$00,$00,
332 $88,$50,$20,$50,$88,$00,$00,$00,$88,$88,$98,$68,$08,$70,$00,$00,$f8,$10,$20,$40,$f8,$00,$18,$20,$20,$40,
333 $20,$20,$18,$00,$20,$20,$20,$00,$20,$20,$20,$00,$c0,$20,$20,$10,$20,$20,$c0,$00,$40,$a8,$10,$00,$00,$00,
334 $00,$00,$00,$00,$20,$50,$f8,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$ff,$f0,$f0,$f0,$f0,$0f,$0f,$0f,$0f,
335 $00,$00,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3c,$3c,$00,$00,$00,$ff,$ff,
336 $ff,$ff,$ff,$ff,$00,$00,$c0,$c0,$c0,$c0,$c0,$c0,$c0,$c0,$0f,$0f,$0f,$0f,$f0,$f0,$f0,$f0,$fc,$fc,$fc,$fc,
337 $fc,$fc,$fc,$fc,$03,$03,$03,$03,$03,$03,$03,$03,$3f,$3f,$3f,$3f,$3f,$3f,$3f,$3f,$11,$22,$44,$88,$11,$22,
338 $44,$88,$88,$44,$22,$11,$88,$44,$22,$11,$fe,$7c,$38,$10,$00,$00,$00,$00,$00,$00,$00,$00,$10,$38,$7c,$fe,
339 $80,$c0,$e0,$f0,$e0,$c0,$80,$00,$01,$03,$07,$0f,$07,$03,$01,$00,$ff,$7e,$3c,$18,$18,$3c,$7e,$ff,$81,$c3,
340 $e7,$ff,$ff,$e7,$c3,$81,$f0,$f0,$f0,$f0,$00,$00,$00,$00,$00,$00,$00,$00,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
341 $00,$00,$00,$00,$00,$00,$00,$00,$f0,$f0,$f0,$f0,$33,$33,$cc,$cc,$33,$33,$cc,$cc,$00,$20,$20,$50,$50,$88,
342 $f8,$00,$20,$20,$70,$20,$70,$20,$20,$00,$00,$00,$00,$50,$88,$a8,$50,$00,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,
343 $00,$00,$00,$00,$ff,$ff,$ff,$ff,$f0,$f0,$f0,$f0,$f0,$f0,$f0,$f0,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$ff,$ff,
344 $ff,$ff,$00,$00,$00,$00,$00,$00,$68,$90,$90,$90,$68,$00,$30,$48,$48,$70,$48,$48,$70,$c0,$f8,$88,$80,$80,
345 $80,$80,$80,$00,$00,$50,$70,$88,$f8,$80,$70,$00,$00,$00,$78,$80,$f0,$80,$78,$00,$00,$00,$78,$90,$90,$90,
346 $60,$00,$20,$00,$60,$20,$20,$20,$70,$00,$50,$00,$70,$20,$20,$20,$70,$00,$f8,$20,$70,$a8,$a8,$70,$20,$f8,
347 $20,$50,$88,$f8,$88,$50,$20,$00,$70,$88,$88,$88,$50,$50,$d8,$00,$30,$40,$40,$20,$50,$50,$50,$20,$00,$00,
348 $00,$50,$a8,$a8,$50,$00,$08,$70,$a8,$a8,$a8,$70,$80,$00,$38,$40,$80,$f8,$80,$40,$38,$00,$70,$88,$88,$88,
349 $88,$88,$88,$00,$00,$f8,$00,$f8,$00,$f8,$00,$00,$20,$20,$f8,$20,$20,$00,$f8,$00,$c0,$30,$08,$30,$c0,$00,
350 $f8,$00,$50,$f8,$80,$f0,$80,$80,$f8,$00,$78,$80,$80,$f0,$80,$80,$78,$00,$20,$20,$20,$20,$20,$20,$a0,$40,
351 $70,$20,$20,$20,$20,$20,$70,$00,$50,$70,$20,$20,$20,$20,$70,$00,$00,$18,$24,$24,$18,$00,$00,$00,$00,$30,
352 $78,$78,$30,$00,$00,$00,$00,$00,$00,$00,$30,$00,$00,$00,$3e,$20,$20,$20,$a0,$60,$20,$00,$a0,$50,$50,$50,
353 $00,$00,$00,$00,$40,$a0,$20,$40,$e0,$00,$00,$00,$00,$38,$38,$38,$38,$38,$38,$00,$3c,$42,$99,$a1,$a1,$99,
354 $42,$3c,$00,$00,$90,$a8,$e8,$a8,$90,$00,$00,$00,$60,$10,$70,$90,$68,$00,$00,$00,$f0,$80,$f0,$88,$f0,$00,
355 $00,$00,$90,$90,$90,$f8,$08,$00,$00,$00,$30,$50,$50,$70,$88,$00,$00,$00,$70,$88,$f8,$80,$70,$00,$00,$20,
356 $70,$a8,$a8,$70,$20,$00,$00,$00,$78,$48,$40,$40,$40,$00,$00,$00,$88,$50,$20,$50,$88,$00,$00,$00,$88,$98,
357 $a8,$c8,$88,$00,$00,$50,$20,$00,$98,$a8,$c8,$00,$00,$00,$90,$a0,$c0,$a0,$90,$00,$00,$00,$38,$28,$28,$48,
358 $88,$00,$00,$00,$88,$d8,$a8,$88,$88,$00,$00,$00,$88,$88,$f8,$88,$88,$00,$00,$00,$70,$88,$88,$88,$70,$00,
359 $00,$00,$78,$48,$48,$48,$48,$00,$00,$00,$78,$88,$78,$28,$48,$00,$00,$00,$f0,$88,$f0,$80,$80,$00,$00,$00,
360 $78,$80,$80,$80,$78,$00,$00,$00,$f8,$20,$20,$20,$20,$00,$00,$00,$88,$50,$20,$40,$80,$00,$00,$00,$a8,$70,
361 $20,$70,$a8,$00,$00,$00,$f0,$48,$70,$48,$f0,$00,$00,$00,$40,$40,$70,$48,$70,$00,$00,$00,$88,$88,$c8,$a8,
362 $c8,$00,$00,$00,$f0,$08,$70,$08,$f0,$00,$00,$00,$a8,$a8,$a8,$a8,$f8,$00,$00,$00,$70,$88,$38,$88,$70,$00,
363 $00,$00,$a8,$a8,$a8,$f8,$08,$00,$00,$00,$48,$48,$78,$08,$08,$00,$00,$00,$c0,$40,$70,$48,$70,$00,$90,$a8,
364 $a8,$e8,$a8,$a8,$90,$00,$20,$50,$88,$88,$f8,$88,$88,$00,$f8,$88,$80,$f0,$88,$88,$f0,$00,$90,$90,$90,$90,
365 $90,$f8,$08,$00,$38,$28,$28,$48,$48,$f8,$88,$00,$f8,$80,$80,$f0,$80,$80,$f8,$00,$20,$70,$a8,$a8,$a8,$70,
366 $20,$00,$f8,$88,$88,$80,$80,$80,$80,$00,$88,$88,$50,$20,$50,$88,$88,$00,$88,$88,$98,$a8,$c8,$88,$88,$00,
367 $50,$20,$88,$98,$a8,$c8,$88,$00,$88,$90,$a0,$c0,$a0,$90,$88,$00,$18,$28,$48,$48,$48,$48,$88,$00,$88,$d8,
368 $a8,$a8,$88,$88,$88,$00,$88,$88,$88,$f8,$88,$88,$88,$00,$70,$88,$88,$88,$88,$88,$70,$00,$f8,$88,$88,$88,
369 $88,$88,$88,$00,$78,$88,$88,$78,$28,$48,$88,$00,$f0,$88,$88,$f0,$80,$80,$80,$00,$70,$88,$80,$80,$80,$88,
370 $70,$00,$f8,$20,$20,$20,$20,$20,$20,$00,$88,$88,$88,$50,$20,$40,$80,$00,$a8,$a8,$70,$20,$70,$a8,$a8,$00,
371 $f0,$48,$48,$70,$48,$48,$f0,$00,$80,$80,$80,$f0,$88,$88,$f0,$00,$88,$88,$88,$c8,$a8,$a8,$c8,$00,$f0,$08,
372 $08,$30,$08,$08,$f0,$00,$a8,$a8,$a8,$a8,$a8,$a8,$f8,$00,$70,$88,$08,$78,$08,$88,$70,$00,$a8,$a8,$a8,$a8,
373 $a8,$f8,$08,$00,$88,$88,$88,$88,$78,$08,$08,$00,$c0,$40,$40,$70,$48,$48,$70,$00
374 );
376 const kgiFont8: array[0..256*8-1] of Byte = (
377 $00,$00,$00,$00,$00,$00,$00,$00,$7e,$81,$a5,$81,$bd,$99,$81,$7e,$7e,$ff,$db,$ff,$c3,$e7,$ff,$7e,$6c,$fe,
378 $fe,$fe,$7c,$38,$10,$00,$10,$38,$7c,$fe,$7c,$38,$10,$00,$38,$7c,$38,$fe,$fe,$d6,$10,$38,$10,$10,$38,$7c,
379 $fe,$7c,$10,$38,$00,$00,$18,$3c,$3c,$18,$00,$00,$ff,$ff,$e7,$c3,$c3,$e7,$ff,$ff,$00,$3c,$66,$42,$42,$66,
380 $3c,$00,$ff,$c3,$99,$bd,$bd,$99,$c3,$ff,$0f,$07,$0f,$7d,$cc,$cc,$cc,$78,$3c,$66,$66,$66,$3c,$18,$7e,$18,
381 $3f,$33,$3f,$30,$30,$70,$f0,$e0,$7f,$63,$7f,$63,$63,$67,$e6,$c0,$99,$5a,$3c,$e7,$e7,$3c,$5a,$99,$80,$e0,
382 $f8,$fe,$f8,$e0,$80,$00,$02,$0e,$3e,$fe,$3e,$0e,$02,$00,$18,$3c,$7e,$18,$18,$7e,$3c,$18,$66,$66,$66,$66,
383 $66,$00,$66,$00,$7f,$db,$db,$7b,$1b,$1b,$1b,$00,$7e,$c3,$78,$cc,$cc,$78,$8c,$f8,$00,$00,$00,$00,$7e,$7e,
384 $7e,$00,$18,$3c,$7e,$18,$7e,$3c,$18,$ff,$18,$3c,$7e,$18,$18,$18,$18,$00,$18,$18,$18,$18,$7e,$3c,$18,$00,
385 $00,$18,$0c,$fe,$0c,$18,$00,$00,$00,$30,$60,$fe,$60,$30,$00,$00,$00,$00,$c0,$c0,$c0,$fe,$00,$00,$00,$24,
386 $66,$ff,$66,$24,$00,$00,$00,$18,$3c,$7e,$ff,$ff,$00,$00,$00,$ff,$ff,$7e,$3c,$18,$00,$00,$00,$00,$00,$00,
387 $00,$00,$00,$00,$30,$78,$78,$30,$30,$00,$30,$00,$6c,$6c,$6c,$00,$00,$00,$00,$00,$6c,$6c,$fe,$6c,$fe,$6c,
388 $6c,$00,$30,$7c,$c0,$78,$0c,$f8,$30,$00,$00,$c6,$cc,$18,$30,$66,$c6,$00,$38,$6c,$38,$76,$dc,$cc,$76,$00,
389 $60,$60,$c0,$00,$00,$00,$00,$00,$18,$30,$60,$60,$60,$30,$18,$00,$60,$30,$18,$18,$18,$30,$60,$00,$00,$66,
390 $3c,$ff,$3c,$66,$00,$00,$00,$30,$30,$fc,$30,$30,$00,$00,$00,$00,$00,$00,$00,$70,$30,$60,$00,$00,$00,$fc,
391 $00,$00,$00,$00,$00,$00,$00,$00,$00,$30,$30,$00,$06,$0c,$18,$30,$60,$c0,$80,$00,$78,$cc,$dc,$fc,$ec,$cc,
392 $78,$00,$30,$f0,$30,$30,$30,$30,$fc,$00,$78,$cc,$0c,$38,$60,$cc,$fc,$00,$78,$cc,$0c,$38,$0c,$cc,$78,$00,
393 $1c,$3c,$6c,$cc,$fe,$0c,$0c,$00,$fc,$c0,$f8,$0c,$0c,$cc,$78,$00,$38,$60,$c0,$f8,$cc,$cc,$78,$00,$fc,$cc,
394 $0c,$18,$30,$60,$60,$00,$78,$cc,$cc,$78,$cc,$cc,$78,$00,$78,$cc,$cc,$7c,$0c,$18,$70,$00,$00,$00,$30,$30,
395 $00,$30,$30,$00,$00,$00,$30,$30,$00,$70,$30,$60,$18,$30,$60,$c0,$60,$30,$18,$00,$00,$00,$fc,$00,$fc,$00,
396 $00,$00,$60,$30,$18,$0c,$18,$30,$60,$00,$78,$cc,$0c,$18,$30,$00,$30,$00,$7c,$c6,$de,$de,$de,$c0,$78,$00,
397 $30,$78,$cc,$cc,$fc,$cc,$cc,$00,$fc,$66,$66,$7c,$66,$66,$fc,$00,$3c,$66,$c0,$c0,$c0,$66,$3c,$00,$fc,$6c,
398 $66,$66,$66,$6c,$fc,$00,$fe,$62,$68,$78,$68,$62,$fe,$00,$fe,$62,$68,$78,$68,$60,$f0,$00,$3c,$66,$c0,$c0,
399 $ce,$66,$3e,$00,$cc,$cc,$cc,$fc,$cc,$cc,$cc,$00,$78,$30,$30,$30,$30,$30,$78,$00,$1e,$0c,$0c,$0c,$cc,$cc,
400 $78,$00,$e6,$66,$6c,$78,$6c,$66,$e6,$00,$f0,$60,$60,$60,$62,$66,$fe,$00,$c6,$ee,$fe,$d6,$c6,$c6,$c6,$00,
401 $c6,$e6,$f6,$de,$ce,$c6,$c6,$00,$38,$6c,$c6,$c6,$c6,$6c,$38,$00,$fc,$66,$66,$7c,$60,$60,$f0,$00,$78,$cc,
402 $cc,$cc,$dc,$78,$1c,$00,$fc,$66,$66,$7c,$78,$6c,$e6,$00,$78,$cc,$e0,$38,$1c,$cc,$78,$00,$fc,$b4,$30,$30,
403 $30,$30,$78,$00,$cc,$cc,$cc,$cc,$cc,$cc,$fc,$00,$cc,$cc,$cc,$cc,$cc,$78,$30,$00,$c6,$c6,$c6,$d6,$fe,$ee,
404 $c6,$00,$c6,$c6,$6c,$38,$6c,$c6,$c6,$00,$cc,$cc,$cc,$78,$30,$30,$78,$00,$fe,$cc,$98,$30,$62,$c6,$fe,$00,
405 $78,$60,$60,$60,$60,$60,$78,$00,$c0,$60,$30,$18,$0c,$06,$02,$00,$78,$18,$18,$18,$18,$18,$78,$00,$10,$38,
406 $6c,$c6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$ff,$30,$30,$18,$00,$00,$00,$00,$00,$00,$00,$78,$0c,
407 $7c,$cc,$76,$00,$e0,$60,$7c,$66,$66,$66,$bc,$00,$00,$00,$78,$cc,$c0,$cc,$78,$00,$1c,$0c,$0c,$7c,$cc,$cc,
408 $76,$00,$00,$00,$78,$cc,$fc,$c0,$78,$00,$38,$6c,$60,$f0,$60,$60,$f0,$00,$00,$00,$76,$cc,$cc,$7c,$0c,$f8,
409 $e0,$60,$6c,$76,$66,$66,$e6,$00,$30,$00,$70,$30,$30,$30,$78,$00,$18,$00,$78,$18,$18,$18,$d8,$70,$e0,$60,
410 $66,$6c,$78,$6c,$e6,$00,$70,$30,$30,$30,$30,$30,$78,$00,$00,$00,$ec,$fe,$d6,$c6,$c6,$00,$00,$00,$f8,$cc,
411 $cc,$cc,$cc,$00,$00,$00,$78,$cc,$cc,$cc,$78,$00,$00,$00,$dc,$66,$66,$7c,$60,$f0,$00,$00,$76,$cc,$cc,$7c,
412 $0c,$1e,$00,$00,$d8,$6c,$6c,$60,$f0,$00,$00,$00,$7c,$c0,$78,$0c,$f8,$00,$10,$30,$7c,$30,$30,$34,$18,$00,
413 $00,$00,$cc,$cc,$cc,$cc,$76,$00,$00,$00,$cc,$cc,$cc,$78,$30,$00,$00,$00,$c6,$c6,$d6,$fe,$6c,$00,$00,$00,
414 $c6,$6c,$38,$6c,$c6,$00,$00,$00,$cc,$cc,$cc,$7c,$0c,$f8,$00,$00,$fc,$98,$30,$64,$fc,$00,$1c,$30,$30,$e0,
415 $30,$30,$1c,$00,$18,$18,$18,$00,$18,$18,$18,$00,$e0,$30,$30,$1c,$30,$30,$e0,$00,$76,$dc,$00,$00,$00,$00,
416 $00,$00,$10,$38,$6c,$c6,$c6,$c6,$fe,$00,$78,$cc,$c0,$cc,$78,$18,$0c,$78,$00,$cc,$00,$cc,$cc,$cc,$7e,$00,
417 $1c,$00,$78,$cc,$fc,$c0,$78,$00,$7e,$c3,$3c,$06,$3e,$66,$3f,$00,$cc,$00,$78,$0c,$7c,$cc,$7e,$00,$e0,$00,
418 $78,$0c,$7c,$cc,$7e,$00,$30,$30,$78,$0c,$7c,$cc,$7e,$00,$00,$00,$7c,$c0,$c0,$7c,$06,$3c,$7e,$c3,$3c,$66,
419 $7e,$60,$3c,$00,$cc,$00,$78,$cc,$fc,$c0,$78,$00,$e0,$00,$78,$cc,$fc,$c0,$78,$00,$cc,$00,$70,$30,$30,$30,
420 $78,$00,$7c,$c6,$38,$18,$18,$18,$3c,$00,$e0,$00,$70,$30,$30,$30,$78,$00,$cc,$30,$78,$cc,$cc,$fc,$cc,$00,
421 $30,$30,$00,$78,$cc,$fc,$cc,$00,$1c,$00,$fc,$60,$78,$60,$fc,$00,$00,$00,$7f,$0c,$7f,$cc,$7f,$00,$3e,$6c,
422 $cc,$fe,$cc,$cc,$ce,$00,$78,$cc,$00,$78,$cc,$cc,$78,$00,$00,$cc,$00,$78,$cc,$cc,$78,$00,$00,$e0,$00,$78,
423 $cc,$cc,$78,$00,$78,$cc,$00,$cc,$cc,$cc,$7e,$00,$00,$e0,$00,$cc,$cc,$cc,$7e,$00,$00,$cc,$00,$cc,$cc,$fc,
424 $0c,$f8,$c6,$38,$7c,$c6,$c6,$7c,$38,$00,$cc,$00,$cc,$cc,$cc,$cc,$78,$00,$18,$18,$7e,$c0,$c0,$7e,$18,$18,
425 $38,$6c,$64,$f0,$60,$e6,$fc,$00,$cc,$cc,$78,$fc,$30,$fc,$30,$00,$f0,$d8,$d8,$f4,$cc,$de,$cc,$0e,$0e,$1b,
426 $18,$7e,$18,$18,$d8,$70,$1c,$00,$78,$0c,$7c,$cc,$7e,$00,$38,$00,$70,$30,$30,$30,$78,$00,$00,$1c,$00,$78,
427 $cc,$cc,$78,$00,$00,$1c,$00,$cc,$cc,$cc,$7e,$00,$00,$f8,$00,$f8,$cc,$cc,$cc,$00,$fc,$00,$cc,$ec,$fc,$dc,
428 $cc,$00,$3c,$6c,$6c,$3e,$00,$7e,$00,$00,$3c,$66,$66,$3c,$00,$7e,$00,$00,$30,$00,$30,$60,$c0,$cc,$78,$00,
429 $00,$00,$00,$fc,$c0,$c0,$00,$00,$00,$00,$00,$fc,$0c,$0c,$00,$00,$c6,$cc,$d8,$3e,$63,$ce,$98,$1f,$c6,$cc,
430 $d8,$f3,$67,$cf,$9f,$03,$00,$18,$00,$18,$18,$3c,$3c,$18,$00,$33,$66,$cc,$66,$33,$00,$00,$00,$cc,$66,$33,
431 $66,$cc,$00,$00,$22,$88,$22,$88,$22,$88,$22,$88,$55,$aa,$55,$aa,$55,$aa,$55,$aa,$dc,$76,$dc,$76,$dc,$76,
432 $dc,$76,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$f8,$18,$18,$18,$18,$18,$f8,$18,$f8,$18,$18,$18,
433 $36,$36,$36,$36,$f6,$36,$36,$36,$00,$00,$00,$00,$fe,$36,$36,$36,$00,$00,$f8,$18,$f8,$18,$18,$18,$36,$36,
434 $f6,$06,$f6,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$36,$00,$00,$fe,$06,$f6,$36,$36,$36,$36,$36,$f6,$06,
435 $fe,$00,$00,$00,$36,$36,$36,$36,$fe,$00,$00,$00,$18,$18,$f8,$18,$f8,$00,$00,$00,$00,$00,$00,$00,$f8,$18,
436 $18,$18,$18,$18,$18,$18,$1f,$00,$00,$00,$18,$18,$18,$18,$ff,$00,$00,$00,$00,$00,$00,$00,$ff,$18,$18,$18,
437 $18,$18,$18,$18,$1f,$18,$18,$18,$00,$00,$00,$00,$ff,$00,$00,$00,$18,$18,$18,$18,$ff,$18,$18,$18,$18,$18,
438 $1f,$18,$1f,$18,$18,$18,$36,$36,$36,$36,$37,$36,$36,$36,$36,$36,$37,$30,$3f,$00,$00,$00,$00,$00,$3f,$30,
439 $37,$36,$36,$36,$36,$36,$f7,$00,$ff,$00,$00,$00,$00,$00,$ff,$00,$f7,$36,$36,$36,$36,$36,$37,$30,$37,$36,
440 $36,$36,$00,$00,$ff,$00,$ff,$00,$00,$00,$36,$36,$f7,$00,$f7,$36,$36,$36,$18,$18,$ff,$00,$ff,$00,$00,$00,
441 $36,$36,$36,$36,$ff,$00,$00,$00,$00,$00,$ff,$00,$ff,$18,$18,$18,$00,$00,$00,$00,$ff,$36,$36,$36,$36,$36,
442 $36,$36,$3f,$00,$00,$00,$18,$18,$1f,$18,$1f,$00,$00,$00,$00,$00,$1f,$18,$1f,$18,$18,$18,$00,$00,$00,$00,
443 $3f,$36,$36,$36,$36,$36,$36,$36,$f7,$36,$36,$36,$18,$18,$ff,$00,$ff,$18,$18,$18,$18,$18,$18,$18,$f8,$00,
444 $00,$00,$00,$00,$00,$00,$1f,$18,$18,$18,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$00,$00,$00,$00,$ff,$ff,$ff,$ff,
445 $f0,$f0,$f0,$f0,$f0,$f0,$f0,$f0,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,$ff,$ff,$ff,$ff,$00,$00,$00,$00,$00,$00,
446 $76,$dc,$c8,$dc,$76,$00,$00,$78,$cc,$f8,$cc,$f8,$c0,$c0,$00,$fe,$c6,$c0,$c0,$c0,$c0,$00,$00,$fe,$6c,$6c,
447 $6c,$6c,$6c,$00,$fe,$66,$30,$18,$30,$66,$fe,$00,$00,$00,$7e,$cc,$cc,$cc,$78,$00,$00,$66,$66,$66,$66,$7c,
448 $60,$c0,$00,$76,$dc,$18,$18,$18,$18,$00,$fc,$30,$78,$cc,$cc,$78,$30,$fc,$38,$6c,$c6,$fe,$c6,$6c,$38,$00,
449 $38,$6c,$c6,$c6,$6c,$6c,$ee,$00,$1c,$30,$18,$7c,$cc,$cc,$78,$00,$00,$00,$7e,$db,$db,$7e,$00,$00,$06,$0c,
450 $7e,$db,$db,$7e,$60,$c0,$3c,$60,$c0,$fc,$c0,$60,$3c,$00,$78,$cc,$cc,$cc,$cc,$cc,$cc,$00,$00,$fc,$00,$fc,
451 $00,$fc,$00,$00,$30,$30,$fc,$30,$30,$00,$fc,$00,$60,$30,$18,$30,$60,$00,$fc,$00,$18,$30,$60,$30,$18,$00,
452 $fc,$00,$0e,$1b,$1b,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$d8,$d8,$70,$30,$30,$00,$fc,$00,$30,$30,$00,
453 $00,$72,$9c,$00,$72,$9c,$00,$00,$38,$6c,$6c,$38,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$00,$00,$00,
454 $00,$00,$18,$00,$00,$00,$0f,$0c,$0c,$0c,$ec,$6c,$3c,$1c,$78,$6c,$6c,$6c,$6c,$00,$00,$00,$78,$0c,$38,$60,
455 $7c,$00,$00,$00,$00,$00,$3c,$3c,$3c,$3c,$00,$00,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
456 );
458 const kgiFont6PropWidth: array[0..256-1] of Byte = (
459 $08,$08,$08,$07,$07,$07,$07,$04,$08,$07,$08,$08,$06,$06,$06,$07,
460 $06,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,
461 $85,$21,$13,$05,$05,$05,$05,$13,$13,$13,$05,$05,$12,$14,$12,$05,
462 $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$21,$12,$05,$05,$05,$05,
463 $05,$05,$05,$05,$05,$05,$05,$05,$05,$13,$05,$05,$05,$05,$05,$05,
464 $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$13,$05,$13,$05,$05,
465 $13,$05,$05,$05,$05,$05,$05,$05,$05,$13,$04,$14,$13,$05,$05,$05,
466 $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$14,$21,$04,$05,$08,
467 $08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$04,
468 $44,$08,$08,$08,$08,$08,$08,$08,$05,$04,$05,$08,$08,$08,$08,$08,
469 $05,$05,$05,$05,$05,$05,$13,$13,$05,$05,$05,$04,$05,$05,$05,$05,
470 $05,$05,$05,$05,$05,$03,$04,$04,$06,$05,$04,$07,$04,$03,$05,$08,
471 $05,$05,$05,$05,$05,$05,$05,$14,$05,$05,$05,$04,$05,$05,$05,$05,
472 $14,$05,$05,$05,$05,$05,$05,$05,$14,$05,$05,$05,$05,$05,$14,$05,
473 $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,
474 $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05
475 );
477 const kgiFont8PropWidth: array[0..256-1] of Byte = (
478 $08,$08,$08,$07,$07,$07,$07,$06,$08,$07,$08,$08,$07,$08,$08,$08,
479 $07,$07,$07,$07,$08,$08,$07,$08,$07,$07,$07,$07,$07,$08,$08,$08,
480 $85,$14,$15,$07,$06,$07,$07,$03,$14,$14,$08,$06,$13,$06,$22,$07,
481 $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$22,$13,$05,$06,$15,$06,
482 $07,$06,$07,$07,$07,$07,$07,$07,$06,$14,$07,$07,$07,$07,$07,$07,
483 $07,$06,$07,$06,$06,$06,$06,$07,$07,$06,$07,$14,$07,$14,$07,$08,
484 $23,$07,$07,$06,$07,$06,$06,$07,$07,$14,$05,$07,$14,$07,$06,$06,
485 $07,$07,$06,$06,$15,$07,$06,$07,$07,$06,$06,$06,$32,$06,$07,$07,
486 $06,$07,$06,$08,$07,$07,$07,$07,$08,$06,$06,$06,$07,$05,$06,$06,
487 $06,$08,$07,$06,$06,$06,$07,$07,$06,$07,$06,$07,$07,$06,$07,$08,
488 $07,$05,$06,$07,$06,$06,$16,$16,$06,$06,$06,$08,$08,$06,$08,$08,
489 $08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,
490 $38,$08,$08,$38,$08,$08,$38,$28,$28,$28,$08,$08,$28,$08,$08,$08,
491 $08,$08,$08,$28,$38,$38,$28,$08,$08,$08,$38,$08,$08,$08,$48,$08,
492 $07,$06,$07,$07,$07,$07,$07,$07,$06,$07,$07,$06,$08,$08,$06,$06,
493 $06,$06,$06,$06,$35,$05,$06,$07,$15,$32,$32,$08,$15,$15,$24,$08
494 );
497 function createFontTexture (constref font: array of Byte; constref fontwdt: array of Byte; prop: Boolean): GLuint;
498 const
499 Width = 16*8;
500 Height = 16*8;
501 var
502 tex, tpp: PByte;
503 b: Byte;
504 cc: Integer;
505 x, y, dx, dy: Integer;
506 begin
507 GetMem(tex, Width*Height*4);
509 for cc := 0 to 255 do
510 begin
511 x := (cc mod 16)*8;
512 y := (cc div 16)*8;
513 for dy := 0 to 7 do
514 begin
515 b := font[cc*8+dy];
516 if prop then b := b shl (fontwdt[cc] shr 4);
517 tpp := tex+((y+dy)*(Width*4))+x*4;
518 for dx := 0 to 7 do
519 begin
520 if ((b and $80) <> 0) then
521 begin
522 tpp^ := 255; Inc(tpp);
523 tpp^ := 255; Inc(tpp);
524 tpp^ := 255; Inc(tpp);
525 tpp^ := 255; Inc(tpp);
526 end
527 else
528 begin
529 tpp^ := 0; Inc(tpp);
530 tpp^ := 0; Inc(tpp);
531 tpp^ := 0; Inc(tpp);
532 tpp^ := 0; Inc(tpp);
533 end;
534 b := (b and $7f) shl 1;
535 end;
536 end;
537 end;
539 glGenTextures(1, @result);
540 if (result = 0) then raise Exception.Create('can''t create Holmes font texture');
542 glBindTexture(GL_TEXTURE_2D, result);
543 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
544 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
546 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
548 //GLfloat[4] bclr = 0.0;
549 //glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bclr.ptr);
551 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA{gltt}, GL_UNSIGNED_BYTE, tex);
552 glFlush();
554 //FreeMem(tex);
555 end;
558 var
559 font6texid: GLuint = 0;
560 font8texid: GLuint = 0;
561 prfont6texid: GLuint = 0;
562 prfont8texid: GLuint = 0;
565 procedure deleteFonts ();
566 begin
567 if (font6texid <> 0) then glDeleteTextures(1, @font6texid);
568 if (font8texid <> 0) then glDeleteTextures(1, @font8texid);
569 if (prfont6texid <> 0) then glDeleteTextures(1, @prfont6texid);
570 if (prfont8texid <> 0) then glDeleteTextures(1, @prfont8texid);
571 font6texid := 0;
572 font8texid := 0;
573 prfont6texid := 0;
574 prfont8texid := 0;
575 end;
578 procedure createFonts ();
579 begin
580 if (font6texid = 0) then font6texid := createFontTexture(kgiFont6, kgiFont6PropWidth, false);
581 if (font8texid = 0) then font8texid := createFontTexture(kgiFont8, kgiFont8PropWidth, false);
582 if (prfont6texid = 0) then prfont6texid := createFontTexture(kgiFont6, kgiFont6PropWidth, true);
583 if (prfont8texid = 0) then prfont8texid := createFontTexture(kgiFont8, kgiFont8PropWidth, true);
584 end;
587 // ////////////////////////////////////////////////////////////////////////// //
588 procedure TScissorSave.save (enableScissoring: Boolean);
589 begin
590 wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0);
591 if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]);
592 //conwritefln('(%d,%d)-(%d,%d)', [scxywh[0], scxywh[1], scxywh[2], scxywh[3]]);
593 if enableScissoring and (not wassc) then glEnable(GL_SCISSOR_TEST);
594 end;
596 procedure TScissorSave.restore ();
597 begin
598 glScissor(scxywh[0], scxywh[1], scxywh[2], scxywh[3]);
599 if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST);
600 end;
602 procedure TScissorSave.combineRect (x, y, w, h: Integer);
603 //var ox, oy, ow, oh: Integer;
604 begin
605 if (w < 1) or (h < 1) then begin glScissor(0, 0, 0, 0); exit; end;
606 y := fuiScrHgt-(y+h);
607 //ox := x; oy := y; ow := w; oh := h;
608 if not intersectRect(x, y, w, h, scxywh[0], scxywh[1], scxywh[2], scxywh[3]) then
609 begin
610 //writeln('oops: COMBINE: old=(', ox, ',', oy, ')-(', ox+ow-1, ',', oy+oh-1, '); sci: (', scxywh[0], ',', scxywh[1], ')-(', scxywh[0]+scxywh[2]-1, ',', scxywh[1]+scxywh[3]-1, ')');
611 //writeln('oops: COMBINE: oldx=<', ox, '-', ox+ow-1, '>; oldy=<', oy, ',', oy+oh-1, '> : scix=<', scxywh[0], '-', scxywh[0]+scxywh[2]-1, '>; sciy=<', scxywh[1], '-', scxywh[1]+scxywh[3]-1, '>');
612 glScissor(0, 0, 0, 0);
613 end
614 else
615 begin
616 glScissor(x, y, w, h);
617 end;
618 end;
621 // ////////////////////////////////////////////////////////////////////////// //
622 // returns `false` if the color is transparent
623 function setupGLColor (r, g, b, a: Integer): Boolean;
624 begin
625 normRGBA(r, g, b, a);
626 if (a < 255) then
627 begin
628 if (a = 0) then begin result := false; exit; end;
629 glEnable(GL_BLEND);
630 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
631 end
632 else
633 begin
634 glDisable(GL_BLEND);
635 end;
636 glColor4ub(Byte(r), Byte(g), Byte(b), Byte(a));
637 result := true;
638 end;
640 // returns `false` if the color is transparent
641 function setupGLColor (constref clr: TGxRGBA): Boolean;
642 begin
643 if (clr.a < 255) then
644 begin
645 if (clr.a = 0) then begin result := false; exit; end;
646 glEnable(GL_BLEND);
647 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
648 end
649 else
650 begin
651 glDisable(GL_BLEND);
652 end;
653 glColor4ub(clr.r, clr.g, clr.b, clr.a);
654 result := true;
655 end;
657 function isScaled (): Boolean;
658 var
659 mt: packed array [0..15] of Double;
660 begin
661 glGetDoublev(GL_MODELVIEW_MATRIX, @mt[0]);
662 result := (mt[0] <> 1.0) or (mt[1*4+1] <> 1.0);
663 end;
666 // ////////////////////////////////////////////////////////////////////////// //
667 function textWidth6 (const s: AnsiString): Integer;
668 var
669 f: Integer;
670 begin
671 result := 0;
672 for f := 1 to Length(s) do Inc(result, Integer(kgiFont6PropWidth[Integer(s[f])] and $0f)+1);
673 if (result > 0) then Dec(result); // don't count last empty pixel
674 end;
677 function textWidth8 (const s: AnsiString): Integer;
678 var
679 f: Integer;
680 begin
681 result := 0;
682 for f := 1 to Length(s) do Inc(result, Integer(kgiFont8PropWidth[Integer(s[f])] and $0f)+1);
683 if (result > 0) then Dec(result); // don't count last empty pixel
684 end;
687 // return width (including last empty pixel)
688 function drawTextInternal (wdt, x, y: Integer; const s: AnsiString; constref clr: TGxRGBA; tid: GLuint; constref fontwdt: array of Byte; prop: Boolean): Integer;
689 var
690 f, c: Integer;
691 tx, ty: Integer;
692 begin
693 result := 0;
694 if (Length(s) = 0) then exit;
695 if not setupGLColor(clr) then exit;
697 glEnable(GL_ALPHA_TEST);
698 glAlphaFunc(GL_NOTEQUAL, 0.0);
699 glEnable(GL_TEXTURE_2D);
700 glBindTexture(GL_TEXTURE_2D, tid);
702 for f := 1 to Length(s) do
703 begin
704 c := Integer(s[f]) and $ff;
705 tx := (c mod 16)*8;
706 ty := (c div 16)*8;
707 glBegin(GL_QUADS);
708 glTexCoord2f((tx+0)/128.0, (ty+0)/128.0); glVertex2i(x+0, y+0); // top-left
709 glTexCoord2f((tx+8)/128.0, (ty+0)/128.0); glVertex2i(x+8, y+0); // top-right
710 glTexCoord2f((tx+8)/128.0, (ty+8)/128.0); glVertex2i(x+8, y+8); // bottom-right
711 glTexCoord2f((tx+0)/128.0, (ty+8)/128.0); glVertex2i(x+0, y+8); // bottom-left
712 glEnd();
713 if prop then
714 begin
715 x += Integer(fontwdt[c] and $0f)+1;
716 result += Integer(fontwdt[c] and $0f)+1;
717 end
718 else
719 begin
720 x += wdt;
721 result += wdt;
722 end;
723 end;
725 glDisable(GL_ALPHA_TEST);
726 glDisable(GL_BLEND);
727 glDisable(GL_TEXTURE_2D);
728 glColor4f(1, 1, 1, 1);
729 glBindTexture(GL_TEXTURE_2D, 0);
730 end;
733 // ////////////////////////////////////////////////////////////////////////// //
734 procedure drawHLine (x, y, len: Integer; constref clr: TGxRGBA);
735 begin
736 if (len < 1) then exit;
737 if not setupGLColor(clr) then exit;
738 glDisable(GL_TEXTURE_2D);
739 if (not isScaled) then
740 begin
741 glLineWidth(1);
742 glBegin(GL_LINES);
743 glVertex2f(x+0.375, y+0.375);
744 glVertex2f(x+len+0.375, y+0.375);
745 glEnd();
746 end
747 else
748 begin
749 glBegin(GL_QUADS);
750 glVertex2i(x, y);
751 glVertex2i(x+len, y);
752 glVertex2i(x+len, y+1);
753 glVertex2i(x, y+1);
754 glEnd();
755 end;
756 end;
759 procedure drawVLine (x, y, len: Integer; constref clr: TGxRGBA);
760 begin
761 if (len < 1) then exit;
762 if not setupGLColor(clr) then exit;
763 glDisable(GL_TEXTURE_2D);
764 if (not isScaled) then
765 begin
766 glLineWidth(1);
767 glBegin(GL_LINES);
768 glVertex2f(x+0.375, y+0.375);
769 glVertex2f(x+0.375, y+len+0.375);
770 glEnd();
771 end
772 else
773 begin
774 glBegin(GL_QUADS);
775 glVertex2i(x, y);
776 glVertex2i(x, y+len);
777 glVertex2i(x+1, y+len);
778 glVertex2i(x+1, y);
779 glEnd();
780 end;
781 end;
784 procedure drawLine (x1, y1, x2, y2: Integer; constref clr: TGxRGBA);
785 begin
786 if not setupGLColor(clr) then exit;
788 glDisable(GL_TEXTURE_2D);
790 glLineWidth(1);
791 glPointSize(1);
793 if (not isScaled) then
794 begin
795 glLineWidth(1);
796 glBegin(GL_LINES);
797 glVertex2f(x1+0.375, y1+0.375);
798 glVertex2f(x2+0.375, y2+0.375);
799 glEnd();
801 if (x1 <> x2) or (y1 <> y2) then
802 begin
803 glBegin(GL_POINTS);
804 glVertex2f(x2+0.375, y2+0.375);
805 glEnd();
806 end;
807 end
808 else
809 begin
810 glLineWidth(1);
811 glBegin(GL_LINES);
812 glVertex2i(x1, y1);
813 glVertex2i(x2, y2);
814 // draw last point
815 glVertex2i(x2, y2);
816 glVertex2i(x2+1, y2+1);
817 glEnd();
818 end;
820 glColor4f(1, 1, 1, 1);
821 glDisable(GL_BLEND);
822 end;
825 procedure drawRect (x, y, w, h: Integer; constref clr: TGxRGBA);
826 begin
827 if (w < 0) or (h < 0) then exit;
828 if not setupGLColor(clr) then exit;
829 glDisable(GL_TEXTURE_2D);
830 glLineWidth(1);
831 glDisable(GL_LINE_SMOOTH);
832 glDisable(GL_POLYGON_SMOOTH);
833 if (w = 1) and (h = 1) then
834 begin
835 glBegin(GL_POINTS);
836 glVertex2f(x+0.375, y+0.375);
837 glEnd();
838 end
839 else
840 begin
841 glLineWidth(1);
842 glBegin(GL_LINES);
843 glVertex2i(x, y); glVertex2i(x+w, y); // top
844 glVertex2i(x, y+h-1); glVertex2i(x+w, y+h-1); // bottom
845 glVertex2f(x+0.375, y+1); glVertex2f(x+0.375, y+h-1); // left
846 glVertex2f(x+w-1+0.375, y+1); glVertex2f(x+w-1+0.375, y+h-1); // right
847 glEnd();
848 end;
849 //glRect(x, y, x+w, y+h);
850 glColor4f(1, 1, 1, 1);
851 glDisable(GL_BLEND);
852 end;
855 procedure drawRectUI (x, y, w, h: Integer; constref clr: TGxRGBA);
856 procedure hline (x, y, len: Integer);
857 begin
858 if (len < 1) then exit;
859 glBegin(GL_QUADS);
860 glVertex2i(x, y);
861 glVertex2i(x+len, y);
862 glVertex2i(x+len, y+1);
863 glVertex2i(x, y+1);
864 glEnd();
865 end;
867 procedure vline (x, y, len: Integer);
868 begin
869 if (len < 1) then exit;
870 glBegin(GL_QUADS);
871 glVertex2i(x, y);
872 glVertex2i(x, y+len);
873 glVertex2i(x+1, y+len);
874 glVertex2i(x+1, y);
875 glEnd();
876 end;
878 var
879 scaled: Boolean;
880 begin
881 if (w < 0) or (h < 0) then exit;
882 if not setupGLColor(clr) then exit;
883 glDisable(GL_TEXTURE_2D);
884 glLineWidth(1);
885 glDisable(GL_LINE_SMOOTH);
886 glDisable(GL_POLYGON_SMOOTH);
887 scaled := isScaled();
888 if (w = 1) and (h = 1) then
889 begin
890 glBegin(GL_POINTS);
891 if scaled then glVertex2i(x, y) else glVertex2f(x+0.375, y+0.375);
892 glEnd();
893 end
894 else
895 begin
896 if not scaled then
897 begin
898 glLineWidth(1);
899 glBegin(GL_LINES);
900 glVertex2i(x, y); glVertex2i(x+w, y); // top
901 glVertex2i(x, y+h-1); glVertex2i(x+w, y+h-1); // bottom
902 glVertex2f(x+0.375, y+1); glVertex2f(x+0.375, y+h-1); // left
903 glVertex2f(x+w-1+0.375, y+1); glVertex2f(x+w-1+0.375, y+h-1); // right
904 glEnd();
905 end
906 else
907 begin
908 hline(x, y, w);
909 hline(x, y+h-1, w);
910 vline(x, y+1, h-2);
911 vline(x+w-1, y+1, h-2);
912 end;
913 end;
914 //glRect(x, y, x+w, y+h);
915 glColor4f(1, 1, 1, 1);
916 glDisable(GL_BLEND);
917 end;
920 procedure darkenRect (x, y, w, h: Integer; a: Integer);
921 begin
922 if (w < 0) or (h < 0) then exit;
923 if (a < 0) then a := 0;
924 if (a >= 255) then exit;
925 glEnable(GL_BLEND);
926 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
927 glDisable(GL_LINE_SMOOTH);
928 glDisable(GL_POLYGON_SMOOTH);
929 glDisable(GL_TEXTURE_2D);
930 glColor4f(0.0, 0.0, 0.0, a/255.0);
931 glBegin(GL_QUADS);
932 glVertex2i(x, y);
933 glVertex2i(x+w, y);
934 glVertex2i(x+w, y+h);
935 glVertex2i(x, y+h);
936 glEnd();
937 //glRect(x, y, x+w, y+h);
938 glColor4f(1, 1, 1, 1);
939 glDisable(GL_BLEND);
940 //glBlendEquation(GL_FUNC_ADD);
941 end;
944 procedure fillRect (x, y, w, h: Integer; constref clr: TGxRGBA);
945 begin
946 if (w < 0) or (h < 0) then exit;
947 if not setupGLColor(clr) then exit;
948 glDisable(GL_LINE_SMOOTH);
949 glDisable(GL_POLYGON_SMOOTH);
950 glDisable(GL_TEXTURE_2D);
951 glBegin(GL_QUADS);
952 glVertex2f(x, y);
953 glVertex2f(x+w, y);
954 glVertex2f(x+w, y+h);
955 glVertex2f(x, y+h);
956 glEnd();
957 glColor4f(1, 1, 1, 1);
958 glDisable(GL_BLEND);
959 end;
962 // ////////////////////////////////////////////////////////////////////////// //
963 function drawText6 (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
964 begin
965 if (font6texid = 0) then createFonts();
966 drawTextInternal(6, x, y, s, clr, font6texid, kgiFont6PropWidth, false);
967 result := Length(s)*6;
968 end;
970 function drawText8 (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
971 begin
972 if (font8texid = 0) then createFonts();
973 drawTextInternal(8, x, y, s, clr, font8texid, kgiFont8PropWidth, false);
974 result := Length(s)*8;
975 end;
977 function drawText6Prop (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
978 begin
979 if (prfont6texid = 0) then createFonts();
980 result := drawTextInternal(6, x, y, s, clr, prfont6texid, kgiFont6PropWidth, true);
981 end;
983 function drawText8Prop (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
984 begin
985 if (prfont8texid = 0) then createFonts();
986 result := drawTextInternal(8, x, y, s, clr, prfont8texid, kgiFont8PropWidth, true);
987 end;
990 // ////////////////////////////////////////////////////////////////////////// //
991 // x-centered at `x`
992 function drawText6XC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
993 begin
994 if (font6texid = 0) then createFonts();
995 x -= Length(s)*6 div 2;
996 drawTextInternal(6, x, y, s, clr, font6texid, kgiFont6PropWidth, false);
997 result := Length(s)*6;
998 end;
1000 function drawText8XC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
1001 begin
1002 if (font8texid = 0) then createFonts();
1003 x -= Length(s)*8 div 2;
1004 drawTextInternal(8, x, y, s, clr, font8texid, kgiFont8PropWidth, false);
1005 result := Length(s)*8;
1006 end;
1008 function drawText6PropXC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
1009 begin
1010 if (prfont6texid = 0) then createFonts();
1011 x -= textWidth6(s) div 2;
1012 result := drawTextInternal(6, x, y, s, clr, prfont6texid, kgiFont6PropWidth, true);
1013 end;
1015 function drawText8PropXC (x, y: Integer; const s: AnsiString; constref clr: TGxRGBA): Integer;
1016 begin
1017 if (prfont8texid = 0) then createFonts();
1018 x -= textWidth8(s) div 2;
1019 result := drawTextInternal(8, x, y, s, clr, prfont8texid, kgiFont8PropWidth, true);
1020 end;
1023 // ////////////////////////////////////////////////////////////////////////// //
1024 procedure oglRestoreMode (doClear: Boolean);
1025 begin
1026 oglSetup2D(fuiScrWdt, fuiScrHgt);
1027 glScissor(0, 0, fuiScrWdt, fuiScrHgt);
1029 glBindTexture(GL_TEXTURE_2D, 0);
1030 glDisable(GL_BLEND);
1031 glDisable(GL_TEXTURE_2D);
1032 glDisable(GL_STENCIL_TEST);
1033 glDisable(GL_SCISSOR_TEST);
1034 glDisable(GL_LIGHTING);
1035 glDisable(GL_DEPTH_TEST);
1036 glDisable(GL_CULL_FACE);
1037 glDisable(GL_LINE_SMOOTH);
1038 glDisable(GL_POINT_SMOOTH);
1039 glLineWidth(1);
1040 glPointSize(1);
1041 glColor4f(1, 1, 1, 1);
1043 if doClear then
1044 begin
1045 glClearColor(0, 0, 0, 0);
1046 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_ACCUM_BUFFER_BIT or GL_STENCIL_BUFFER_BIT);
1047 end;
1049 // scale everything
1050 glMatrixMode(GL_MODELVIEW);
1051 glLoadIdentity();
1052 //glScalef(4, 4, 1);
1053 end;
1056 //procedure onWinFocus (); begin end;
1057 //procedure onWinBlur (); begin fuiResetKMState(true); end;
1059 procedure onPreRender (); begin oglRestoreMode(gGfxDoClear); end;
1061 procedure onPostRender (); begin oglRestoreMode(false); oglDrawCursor(); end;
1063 procedure onInit ();
1064 begin
1065 oglSetup2D(fuiScrWdt, fuiScrHgt);
1067 createCursorTexture();
1068 createFonts();
1069 end;
1071 procedure onDeinit ();
1072 begin
1073 fuiResetKMState(false);
1074 if (curtexid <> 0) then glDeleteTextures(1, @curtexid);
1075 curtexid := 0;
1076 deleteFonts();
1077 fuiSetButState(0);
1078 fuiSetModState(0);
1079 fuiSetMouseX(0);
1080 fuiSetMouseY(0);
1081 end;
1084 // ////////////////////////////////////////////////////////////////////////// //
1085 begin
1086 //winFocusCB := onWinFocus;
1087 //winBlurCB := onWinBlur;
1088 prerenderFrameCB := onPreRender;
1089 postrenderFrameCB := onPostRender;
1090 oglInitCB := onInit;
1091 oglDeinitCB := onDeinit;
1092 end.