1 (* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
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.
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.
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/>.
17 {$INCLUDE ../shared/a_modes.inc}
26 fui_common
, fui_events
;
29 // ////////////////////////////////////////////////////////////////////////// //
38 function charWidth (const ch
: AnsiChar): Integer; virtual; abstract;
39 function textWidth (const s
: AnsiString): Integer; virtual; abstract;
42 property name
: AnsiString read mName
;
43 property height
: Integer read mHeight
;
44 property baseLine
: Integer read mBaseLine
;
64 // for active contexts
71 function getFont (): AnsiString;
72 procedure setFont (const aname
: AnsiString);
74 procedure onActivate ();
75 procedure onDeactivate ();
77 procedure setColor (const clr
: TGxRGBA
);
79 procedure realizeClip (); // setup scissoring
81 procedure setClipOfs (const aofs
: TGxOfs
);
82 procedure setClipRect (const aclip
: TGxRect
);
85 constructor Create ();
86 destructor Destroy (); override;
88 procedure line (x1
, y1
, x2
, y2
: Integer);
89 procedure hline (x
, y
, len
: Integer);
90 procedure vline (x
, y
, len
: Integer);
91 procedure rect (x
, y
, w
, h
: Integer);
92 procedure fillRect (x
, y
, w
, h
: Integer);
93 procedure darkenRect (x
, y
, w
, h
: Integer; a
: Integer);
95 function charWidth (const ch
: AnsiChar): Integer;
96 function charHeight (const ch
: AnsiChar): Integer;
97 function textWidth (const s
: AnsiString): Integer;
98 function textHeight (const s
: AnsiString): Integer;
99 function drawChar (x
, y
: Integer; const ch
: AnsiChar): Integer; // returns char width
100 function drawText (x
, y
: Integer; const s
: AnsiString): Integer; // returns text width
102 function iconMarkWidth (ic
: TMarkIcon
): Integer;
103 function iconMarkHeight (ic
: TMarkIcon
): Integer;
104 procedure drawIconMark (ic
: TMarkIcon
; x
, y
: Integer; marked
: Boolean);
106 function iconWinWidth (ic
: TWinIcon
): Integer;
107 function iconWinHeight (ic
: TWinIcon
): Integer;
108 procedure drawIconWin (ic
: TWinIcon
; x
, y
: Integer; pressed
: Boolean);
110 procedure resetClip ();
112 function setOffset (constref aofs
: TGxOfs
): TGxOfs
; // returns previous offset
113 function setClip (constref aclip
: TGxRect
): TGxRect
; // returns previous clip
115 function combineClip (constref aclip
: TGxRect
): TGxRect
; // returns previous clip
118 property active
: Boolean read mActive
;
119 property color
: TGxRGBA read mColor write setColor
;
120 property font
: AnsiString read getFont write setFont
;
121 property offset
: TGxOfs read mClipOfs write setClipOfs
;
122 property clip
: TGxRect read mClipRect write setClipRect
; // clipping is unaffected by offset
126 // set active context; `ctx` can be `nil`
127 procedure gxSetContext (ctx
: TGxContext
; ascale
: Single=1.0);
130 // setup 2D OpenGL mode; will be called automatically in `glInit()`
131 procedure oglSetup2D (winWidth
, winHeight
: Integer; upsideDown
: Boolean=false);
133 procedure oglDrawCursor ();
134 procedure oglDrawCursorAt (msX
, msY
: Integer);
138 // ////////////////////////////////////////////////////////////////////////// //
140 gGfxDoClear
: Boolean = true;
146 // ////////////////////////////////////////////////////////////////////////// //
147 //TODO: OpenGL framebuffers and shaders state
149 TSavedGLState
= record
152 gltextbinding
: GLint
;
154 //oldfbr, oldfbw: GLint;
155 glvport
: packed array [0..3] of GLint
;
159 constructor Create (dosave
: Boolean);
161 procedure restore ();
164 constructor TSavedGLState
.Create (dosave
: Boolean);
166 FillChar(self
, sizeof(self
), 0);
167 if (dosave
) then save();
170 procedure TSavedGLState
.save ();
172 if (saved
) then raise Exception
.Create('cannot save into already saved OpenGL state');
173 glGetIntegerv(GL_MATRIX_MODE
, @glmatmode
);
174 glGetIntegerv(GL_TEXTURE_BINDING_2D
, @gltextbinding
);
175 glGetIntegerv(GL_VIEWPORT
, @glvport
[0]);
176 //glGetIntegerv(GL_CURRENT_PROGRAM, &oldprg);
177 //glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldfbr);
178 //glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfbw);
179 glMatrixMode(GL_PROJECTION
); glPushMatrix();
180 glMatrixMode(GL_MODELVIEW
); glPushMatrix();
181 glMatrixMode(GL_TEXTURE
); glPushMatrix();
182 glMatrixMode(GL_COLOR
); glPushMatrix();
183 glPushAttrib({GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_CURRENT_BIT}GL_ALL_ATTRIB_BITS
); // let's play safe
187 procedure TSavedGLState
.restore ();
189 if (not saved
) then raise Exception
.Create('cannot restore unsaved OpenGL state');
190 glPopAttrib({GL_ENABLE_BIT});
191 glMatrixMode(GL_PROJECTION
); glPopMatrix();
192 glMatrixMode(GL_MODELVIEW
); glPopMatrix();
193 glMatrixMode(GL_TEXTURE
); glPopMatrix();
194 glMatrixMode(GL_COLOR
); glPopMatrix();
195 glMatrixMode(glmatmode
);
196 //if (glHasFunc!"glBindFramebufferEXT") glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oldfbr);
197 //if (glHasFunc!"glBindFramebufferEXT") glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, oldfbw);
198 glBindTexture(GL_TEXTURE_2D
, gltextbinding
);
199 //if (glHasFunc!"glUseProgram") glUseProgram(oldprg);
200 glViewport(glvport
[0], glvport
[1], glvport
[2], glvport
[3]);
206 curCtx
: TGxContext
= nil;
207 savedGLState
: TSavedGLState
;
210 // ////////////////////////////////////////////////////////////////////////// //
211 // set active context; `ctx` can be `nil`
212 procedure gxSetContext (ctx
: TGxContext
; ascale
: Single=1.0);
214 if (savedGLState
.saved
) then savedGLState
.restore();
216 if (curCtx
<> nil) then
218 curCtx
.onDeactivate();
219 curCtx
.mActive
:= false;
227 oglSetup2D(fuiScrWdt
, fuiScrHgt
);
228 glScalef(ascale
, ascale
, 1.0);
229 ctx
.mScaled
:= (ascale
<> 1.0);
230 ctx
.mScale
:= ascale
;
236 // ////////////////////////////////////////////////////////////////////////// //
238 TScissorSave
= record
241 scxywh
: packed array[0..3] of GLint
;
246 procedure save (enableScissoring
: Boolean);
247 procedure restore ();
249 // set new scissor rect, bounded by the saved scissor rect
250 procedure combineRect (x
, y
, w
, h
: Integer);
254 procedure TScissorSave
.save (enableScissoring
: Boolean);
256 wassc
:= (glIsEnabled(GL_SCISSOR_TEST
) <> 0);
257 if wassc
then glGetIntegerv(GL_SCISSOR_BOX
, @scxywh
[0]) else glGetIntegerv(GL_VIEWPORT
, @scxywh
[0]);
258 //conwritefln('(%d,%d)-(%d,%d)', [scxywh[0], scxywh[1], scxywh[2], scxywh[3]]);
259 if enableScissoring
and (not wassc
) then glEnable(GL_SCISSOR_TEST
);
262 procedure TScissorSave
.restore ();
264 glScissor(scxywh
[0], scxywh
[1], scxywh
[2], scxywh
[3]);
265 if wassc
then glEnable(GL_SCISSOR_TEST
) else glDisable(GL_SCISSOR_TEST
);
268 procedure TScissorSave
.combineRect (x
, y
, w
, h
: Integer);
269 //var ox, oy, ow, oh: Integer;
271 if (w
< 1) or (h
< 1) then begin glScissor(0, 0, 0, 0); exit
; end;
272 y
:= fuiScrHgt
-(y
+h
);
273 //ox := x; oy := y; ow := w; oh := h;
274 if not intersectRect(x
, y
, w
, h
, scxywh
[0], scxywh
[1], scxywh
[2], scxywh
[3]) then
276 //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, ')');
277 //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, '>');
278 glScissor(0, 0, 0, 0);
282 glScissor(x
, y
, w
, h
);
287 // ////////////////////////////////////////////////////////////////////////// //
288 {$INCLUDE fui_gfx_gl_fonts.inc}
291 TGxBmpFont
= class(TGxFont
)
293 mTexId
: GLuint
; // OpenGL texture id
294 mWidth
: Integer; // <=0: proportional
297 mFreeFontWdt
: Boolean;
300 procedure oglCreateTexture ();
301 procedure oglDestroyTexture ();
303 function drawTextInternal (x
, y
: Integer; const s
: AnsiString): Integer; // return width (not including last empty pixel)
306 constructor Create (const aname
: AnsiString; awdt
, ahgt
: Integer; const afont
: PByte; const awdtable
: PByte=nil);
307 destructor Destroy (); override;
309 function charWidth (const ch
: AnsiChar): Integer; override;
310 function textWidth (const s
: AnsiString): Integer; override;
314 constructor TGxBmpFont
.Create (const aname
: AnsiString; awdt
, ahgt
: Integer; const afont
: PByte; const awdtable
: PByte=nil);
318 if (afont
= nil) then raise Exception
.Create('internal error in font creation');
319 if (ahgt
< 1) then raise Exception
.Create('internal error in font creation');
322 //if (awdtable <> nil) then raise Exception.Create('internal error in font creation');
323 mFreeFontWdt
:= true;
324 // create width table
325 GetMem(mFontWdt
, 256);
326 for c
:= 0 to 255 do mFontWdt
[c
] := awdt
-1;
330 if (awdtable
= nil) then raise Exception
.Create('internal error in font creation');
332 mFontWdt
:= awdtable
;
337 mBaseLine
:= ahgt
-1; //FIXME
343 destructor TGxBmpFont
.Destroy ();
345 if (mFreeFontWdt
) and (mFontWdt
<> nil) then FreeMem(mFontWdt
);
352 mFreeFontWdt
:= false;
358 procedure TGxBmpFont
.oglCreateTexture ();
360 mTexId
:= createFontTexture(mFontBmp
, mFontWdt
, (mWidth
<= 0));
364 procedure TGxBmpFont
.oglDestroyTexture ();
366 if (mTexId
<> 0) then
368 glDeleteTextures(1, @mTexId
);
374 function TGxBmpFont
.charWidth (const ch
: AnsiChar): Integer;
376 result
:= (mFontWdt
[Byte(ch
)] and $0f);
380 function TGxBmpFont
.textWidth (const s
: AnsiString): Integer;
384 if (Length(s
) > 0) then
387 for ch
in s
do result
+= (mFontWdt
[Byte(ch
)] and $0f)+1;
396 // return width (not including last empty pixel)
397 function TGxBmpFont
.drawTextInternal (x
, y
: Integer; const s
: AnsiString): Integer;
402 if (Length(s
) = 0) then begin result
:= 0; exit
; end;
406 glEnable(GL_ALPHA_TEST
);
407 glAlphaFunc(GL_NOTEQUAL
, 0.0);
408 glEnable(GL_TEXTURE_2D
);
409 glBindTexture(GL_TEXTURE_2D
, mTexId
);
413 tx
:= (Integer(ch
) mod 16)*8;
414 ty
:= (Integer(ch
) div 16)*8;
416 glTexCoord2f((tx
+0)/128.0, (ty
+0)/128.0); glVertex2i(x
+0, y
+0); // top-left
417 glTexCoord2f((tx
+8)/128.0, (ty
+0)/128.0); glVertex2i(x
+8, y
+0); // top-right
418 glTexCoord2f((tx
+8)/128.0, (ty
+8)/128.0); glVertex2i(x
+8, y
+8); // bottom-right
419 glTexCoord2f((tx
+0)/128.0, (ty
+8)/128.0); glVertex2i(x
+0, y
+8); // bottom-left
421 x
+= (mFontWdt
[Byte(ch
)] and $0f)+1;
422 result
+= (mFontWdt
[Byte(ch
)] and $0f)+1;
425 glDisable(GL_ALPHA_TEST
);
426 glDisable(GL_TEXTURE_2D
);
427 glBindTexture(GL_TEXTURE_2D
, 0);
431 // ////////////////////////////////////////////////////////////////////////// //
433 fontList
: array of TGxBmpFont
= nil;
434 defaultFontName
: AnsiString = 'dos';
437 function strEquCI (const s0
, s1
: AnsiString): Boolean;
442 result
:= (Length(s0
) = Length(s1
));
445 for f
:= 1 to Length(s0
) do
448 if (c0
>= 'a') and (c0
<= 'z') then Dec(c0
, 32); // poor man's `toupper()`
450 if (c1
>= 'a') and (c1
<= 'z') then Dec(c1
, 32); // poor man's `toupper()`
451 if (c0
<> c1
) then begin result
:= false; exit
; end;
457 function getFontByName (const aname
: AnsiString): TGxBmpFont
;
462 if (Length(fontList
) = 0) then raise Exception
.Create('font subsystem not initialized');
463 if (Length(aname
) = 0) or (strEquCI(aname
, 'default')) then fname
:= defaultFontName
else fname
:= aname
;
464 for f
:= 0 to High(fontList
) do
466 result
:= fontList
[f
];
467 if (result
= nil) then continue
;
468 if (strEquCI(result
.name
, fname
)) then exit
;
470 if (fontList
[0] = nil) then raise Exception
.Create('font subsystem not properly initialized');
471 result
:= fontList
[0];
475 procedure deleteFonts ();
479 for f
:= 0 to High(fontList
) do freeAndNil(fontList
[f
]);
484 procedure createFonts ();
487 SetLength(fontList
, 4);
488 fontList
[0] := TGxBmpFont
.Create('dos', 8, 8, @kgiFont8
[0], @kgiFont8PropWidth
[0]);
489 fontList
[1] := TGxBmpFont
.Create('dos-prop', 0, 8, @kgiFont8
[0], @kgiFont8PropWidth
[0]);
490 fontList
[2] := TGxBmpFont
.Create('msx', 6, 8, @kgiFont6
[0], @kgiFont6PropWidth
[0]);
491 fontList
[3] := TGxBmpFont
.Create('msx-prop', 0, 8, @kgiFont6
[0], @kgiFont6PropWidth
[0]);
495 procedure oglInitFonts ();
499 for f
:= 0 to High(fontList
) do if (fontList
[f
] <> nil) then fontList
[f
].oglCreateTexture();
503 procedure oglDeinitFonts ();
507 for f
:= 0 to High(fontList
) do if (fontList
[f
] <> nil) then fontList
[f
].oglDestroyTexture();
511 // ////////////////////////////////////////////////////////////////////////// //
512 procedure oglSetup2D (winWidth
, winHeight
: Integer; upsideDown
: Boolean=false);
514 glViewport(0, 0, winWidth
, winHeight
);
517 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
518 glDisable(GL_LINE_SMOOTH
);
519 glDisable(GL_POLYGON_SMOOTH
);
520 glDisable(GL_POINT_SMOOTH
);
521 glDisable(GL_DEPTH_TEST
);
522 glDisable(GL_TEXTURE_2D
);
523 glDisable(GL_LIGHTING
);
524 glDisable(GL_DITHER
);
525 glDisable(GL_STENCIL_TEST
);
526 glDisable(GL_SCISSOR_TEST
);
527 glDisable(GL_CULL_FACE
);
528 glDisable(GL_ALPHA_TEST
);
530 glMatrixMode(GL_TEXTURE
);
533 glMatrixMode(GL_COLOR
);
536 glMatrixMode(GL_PROJECTION
);
540 glOrtho(0, winWidth
, 0, winHeight
, -1, 1); // set origin to bottom left
544 glOrtho(0, winWidth
, winHeight
, 0, -1, 1); // set origin to top left
547 glMatrixMode(GL_MODELVIEW
);
550 glClearColor(0, 0, 0, 0);
551 glColor4f(1, 1, 1, 1);
555 // ////////////////////////////////////////////////////////////////////////// //
556 {$INCLUDE fui_gfx_gl_cursor.inc}
558 procedure oglDrawCursor (); begin oglDrawCursorAt(fuiMouseX
, fuiMouseY
); end;
561 // ////////////////////////////////////////////////////////////////////////// //
562 // returns `false` if the color is transparent
563 // returns `false` if the color is transparent
564 function setupGLColor (constref clr
: TGxRGBA
): Boolean;
566 if (clr
.a
< 255) then
569 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
575 glColor4ub(clr
.r
, clr
.g
, clr
.b
, clr
.a
);
576 result
:= (clr
.a
<> 0);
579 function mScaled (): Boolean;
581 mt
: packed array [0..15] of Double;
583 glGetDoublev(GL_MODELVIEW_MATRIX
, @mt
[0]);
584 result
:= (mt
[0] <> 1.0) or (mt
[1*4+1] <> 1.0);
588 // ////////////////////////////////////////////////////////////////////////// //
589 constructor TGxContext
.Create ();
592 mColor
:= TGxRGBA
.Create(255, 255, 255);
593 mFont
:= getFontByName('default');
596 mClipRect
:= TGxRect
.Create(0, 0, 8192, 8192);
597 mClipOfs
:= TGxOfs
.Create(0, 0);
601 destructor TGxContext
.Destroy ();
603 if (mActive
) then gxSetContext(nil);
608 function TGxContext
.getFont (): AnsiString;
610 result
:= mFont
.name
;
613 procedure TGxContext
.setFont (const aname
: AnsiString);
615 mFont
:= getFontByName(aname
);
619 procedure TGxContext
.onActivate ();
621 setupGLColor(mColor
);
625 procedure TGxContext
.onDeactivate ();
630 procedure TGxContext
.setColor (const clr
: TGxRGBA
);
633 if (mActive
) then setupGLColor(mColor
);
637 procedure TGxContext
.realizeClip ();
639 sx
, sy
, sw
, sh
: Integer;
641 if (not mActive
) then exit
; // just in case
642 if (mClipRect
.w
<= 0) or (mClipRect
.h
<= 0) then
644 glEnable(GL_SCISSOR_TEST
);
645 glScissor(0, 0, 0, 0);
651 sx
:= trunc(mClipRect
.x
*mScale
);
652 sy
:= trunc(mClipRect
.y
*mScale
);
653 sw
:= trunc(mClipRect
.w
*mScale
);
654 sh
:= trunc(mClipRect
.h
*mScale
);
663 if (not intersectRect(sx
, sy
, sw
, sh
, 0, 0, fuiScrWdt
, fuiScrHgt
)) then
665 glEnable(GL_SCISSOR_TEST
);
666 glScissor(0, 0, 0, 0);
668 else if (sx
= 0) and (sy
= 0) and (sw
= fuiScrWdt
) and (sh
= fuiScrHgt
) then
670 glDisable(GL_SCISSOR_TEST
);
674 glEnable(GL_SCISSOR_TEST
);
675 sy
:= fuiScrHgt
-(sy
+sh
);
676 glScissor(sx
, sy
, sw
, sh
);
682 procedure TGxContext
.resetClip ();
684 mClipRect
:= TGxRect
.Create(0, 0, 8192, 8192);
685 if (mActive
) then realizeClip();
689 procedure TGxContext
.setClipOfs (const aofs
: TGxOfs
);
695 procedure TGxContext
.setClipRect (const aclip
: TGxRect
);
698 if (mActive
) then realizeClip();
702 function TGxContext
.setOffset (constref aofs
: TGxOfs
): TGxOfs
;
709 function TGxContext
.setClip (constref aclip
: TGxRect
): TGxRect
;
713 if (mActive
) then realizeClip();
717 function TGxContext
.combineClip (constref aclip
: TGxRect
): TGxRect
;
720 mClipRect
.intersect(aclip
);
721 if (mActive
) then realizeClip();
725 procedure TGxContext
.line (x1
, y1
, x2
, y2
: Integer);
727 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
729 if (not mScaled
) then
733 glVertex2f(x1
+0.375, y1
+0.375);
734 glVertex2f(x2
+0.375, y2
+0.375);
737 if (x1
<> x2
) or (y1
<> y2
) then
741 glVertex2f(x2
+0.375, y2
+0.375);
753 glVertex2i(x2
+1, y2
+1);
759 procedure TGxContext
.hline (x
, y
, len
: Integer);
761 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
762 if (len
< 1) then exit
;
763 if (not mScaled
) then
767 glVertex2f(x
+0.375, y
+0.375);
768 glVertex2f(x
+len
+0.375, y
+0.375);
775 glVertex2i(x
+len
, y
);
776 glVertex2i(x
+len
, y
+1);
783 procedure TGxContext
.vline (x
, y
, len
: Integer);
785 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
786 if (len
< 1) then exit
;
787 if (not mScaled
) then
791 glVertex2f(x
+0.375, y
+0.375);
792 glVertex2f(x
+0.375, y
+len
+0.375);
799 glVertex2i(x
, y
+len
);
800 glVertex2i(x
+1, y
+len
);
807 procedure TGxContext
.rect (x
, y
, w
, h
: Integer);
808 procedure hlinex (x
, y
, len
: Integer);
810 if (len
< 1) then exit
;
813 glVertex2i(x
+len
, y
);
814 glVertex2i(x
+len
, y
+1);
819 procedure vlinex (x
, y
, len
: Integer);
821 if (len
< 1) then exit
;
824 glVertex2i(x
, y
+len
);
825 glVertex2i(x
+1, y
+len
);
831 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
832 if (w
< 0) or (h
< 0) then exit
;
833 if (w
= 1) and (h
= 1) then
837 if mScaled
then glVertex2i(x
, y
) else glVertex2f(x
+0.375, y
+0.375);
842 if (not mScaled
) then
846 glVertex2i(x
, y
); glVertex2i(x
+w
, y
); // top
847 glVertex2i(x
, y
+h
-1); glVertex2i(x
+w
, y
+h
-1); // bottom
848 glVertex2f(x
+0.375, y
+1); glVertex2f(x
+0.375, y
+h
-1); // left
849 glVertex2f(x
+w
-1+0.375, y
+1); glVertex2f(x
+w
-1+0.375, y
+h
-1); // right
857 vlinex(x
+w
-1, y
+1, h
-2);
863 procedure TGxContext
.fillRect (x
, y
, w
, h
: Integer);
865 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
866 if (w
< 0) or (h
< 0) then exit
;
870 glVertex2f(x
+w
, y
+h
);
876 procedure TGxContext
.darkenRect (x
, y
, w
, h
: Integer; a
: Integer);
878 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (a
>= 255) then exit
;
879 if (w
< 0) or (h
< 0) then exit
;
880 if (a
< 0) then a
:= 0;
882 glBlendFunc(GL_ZERO
, GL_SRC_ALPHA
);
883 glColor4f(0.0, 0.0, 0.0, a
/255.0);
887 glVertex2i(x
+w
, y
+h
);
890 setupGLColor(mColor
);
894 function TGxContext
.charWidth (const ch
: AnsiChar): Integer;
896 result
:= mFont
.charWidth(ch
);
899 function TGxContext
.charHeight (const ch
: AnsiChar): Integer;
901 result
:= mFont
.height
;
905 function TGxContext
.textWidth (const s
: AnsiString): Integer;
907 result
:= mFont
.textWidth(s
);
910 function TGxContext
.textHeight (const s
: AnsiString): Integer;
912 result
:= mFont
.height
;
916 function TGxContext
.drawChar (x
, y
: Integer; const ch
: AnsiChar): Integer; // returns char width
918 result
:= mFont
.charWidth(ch
);
919 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
920 TGxBmpFont(mFont
).drawTextInternal(x
, y
, ch
);
923 function TGxContext
.drawText (x
, y
: Integer; const s
: AnsiString): Integer; // returns text width
925 result
:= mFont
.textWidth(s
);
926 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) or (Length(s
) = 0) then exit
;
927 TGxBmpFont(mFont
).drawTextInternal(x
, y
, s
);
931 function TGxContext
.iconMarkWidth (ic
: TMarkIcon
): Integer; begin result
:= 11; end;
932 function TGxContext
.iconMarkHeight (ic
: TMarkIcon
): Integer; begin result
:= 8; end;
934 procedure TGxContext
.drawIconMark (ic
: TMarkIcon
; x
, y
: Integer; marked
: Boolean);
938 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
939 if (ic
= TMarkIcon
.Checkbox
) then
957 if (not marked
) then exit
;
963 vline(x
+3+f
, y
+1+f
, 1);
964 vline(x
+7-f
, y
+1+f
, 1);
979 function TGxContext
.iconWinWidth (ic
: TWinIcon
): Integer; begin result
:= 9; end;
980 function TGxContext
.iconWinHeight (ic
: TWinIcon
): Integer; begin result
:= 8; end;
982 procedure TGxContext
.drawIconWin (ic
: TWinIcon
; x
, y
: Integer; pressed
: Boolean);
986 if (not mActive
) or (mClipRect
.w
< 1) or (mClipRect
.h
< 1) or (mColor
.a
= 0) then exit
;
987 if pressed
then rect(x
, y
, 9, 8);
990 vline(x
+1+f
, y
+f
, 1);
991 vline(x
+1+6-f
, y
+f
, 1);
996 // ////////////////////////////////////////////////////////////////////////// //
998 procedure oglRestoreMode (doClear: Boolean);
1000 oglSetup2D(fuiScrWdt, fuiScrHgt);
1001 glScissor(0, 0, fuiScrWdt, fuiScrHgt);
1003 glBindTexture(GL_TEXTURE_2D, 0);
1004 glDisable(GL_BLEND);
1005 glDisable(GL_TEXTURE_2D);
1006 glDisable(GL_STENCIL_TEST);
1007 glDisable(GL_SCISSOR_TEST);
1008 glDisable(GL_LIGHTING);
1009 glDisable(GL_DEPTH_TEST);
1010 glDisable(GL_CULL_FACE);
1011 glDisable(GL_LINE_SMOOTH);
1012 glDisable(GL_POINT_SMOOTH);
1015 glColor4f(1, 1, 1, 1);
1019 glClearColor(0, 0, 0, 0);
1020 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_ACCUM_BUFFER_BIT or GL_STENCIL_BUFFER_BIT);
1024 glMatrixMode(GL_MODELVIEW);
1026 //glScalef(4, 4, 1);
1031 //procedure onWinFocus (); begin end;
1032 //procedure onWinBlur (); begin fuiResetKMState(true); end;
1034 //procedure onPreRender (); begin oglRestoreMode(gGfxDoClear); end;
1035 procedure onPostRender (); begin oglDrawCursor(); end;
1037 procedure onInit ();
1039 //oglSetup2D(fuiScrWdt, fuiScrHgt);
1040 createCursorTexture();
1044 procedure onDeinit ();
1046 fuiResetKMState(false);
1047 if (curtexid
<> 0) then glDeleteTextures(1, @curtexid
);
1057 // ////////////////////////////////////////////////////////////////////////// //
1059 savedGLState
:= TSavedGLState
.Create(false);
1061 //winFocusCB := onWinFocus;
1062 //winBlurCB := onWinBlur;
1063 //prerenderFrameCB := onPreRender;
1064 postrenderFrameCB
:= onPostRender
;
1065 oglInitCB
:= onInit
;
1066 oglDeinitCB
:= onDeinit
;