X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fflexui%2Ffui_gfx_gl.pas;h=e543fc0e7023a9700a08ddf705f83f439aa8958c;hb=ca23794a6f2dc5eb454f65fc53efc265f16de612;hp=b0ccd2285e7af84a8ffa1f8e8444a1ebfca45378;hpb=b4265979da0b4b264d3cd4685af9566d6ae37f2f;p=d2df-sdl.git diff --git a/src/flexui/fui_gfx_gl.pas b/src/flexui/fui_gfx_gl.pas index b0ccd22..e543fc0 100644 --- a/src/flexui/fui_gfx_gl.pas +++ b/src/flexui/fui_gfx_gl.pas @@ -3,8 +3,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,13 +14,15 @@ * along with this program. If not, see . *) {$INCLUDE ../shared/a_modes.inc} +{$DEFINE FUI_TEXT_ICONS} unit fui_gfx_gl; interface uses + {$INCLUDE ../nogl/noGLuses.inc} SysUtils, Classes, - GL, GLExt, SDL2, + SDL2, sdlcarcass, fui_common, fui_events; @@ -114,6 +115,19 @@ type function combineClip (constref aclip: TGxRect): TGxRect; // returns previous clip + // vertical scrollbar + procedure drawVSBar (x, y, wdt, hgt: Integer; cur, min, max: Integer; constref clrfull, clrempty: TGxRGBA); + // horizontal scrollbar + procedure drawHSBar (x, y, wdt, hgt: Integer; cur, min, max: Integer; constref clrfull, clrempty: TGxRGBA); + + class function sbarFilled (wh: Integer; cur, min, max: Integer): Integer; + class function sbarPos (cxy: Integer; xy, wh: Integer; min, max: Integer): Integer; + + public //HACK! + procedure glSetScale (ascale: Single); + procedure glSetTrans (ax, ay: Single); + procedure glSetScaleTrans (ascale, ax, ay: Single); + public property active: Boolean read mActive; property color: TGxRGBA read mColor write setColor; @@ -125,15 +139,20 @@ type // set active context; `ctx` can be `nil` procedure gxSetContext (ctx: TGxContext; ascale: Single=1.0); +procedure gxSetContextNoMatrix (ctx: TGxContext); // setup 2D OpenGL mode; will be called automatically in `glInit()` procedure oglSetup2D (winWidth, winHeight: Integer; upsideDown: Boolean=false); +procedure oglSetup2DState (); // don't modify viewports and matrices procedure oglDrawCursor (); procedure oglDrawCursorAt (msX, msY: Integer); +procedure fuiGfxLoadFont (const fontname: AnsiString; const fontFile: AnsiString; proportional: Boolean=false); +procedure fuiGfxLoadFont (const fontname: AnsiString; st: TStream; proportional: Boolean=false); + // ////////////////////////////////////////////////////////////////////////// // var @@ -142,6 +161,37 @@ var implementation +uses + fui_wadread, + utils; + + +// ////////////////////////////////////////////////////////////////////////// // +// returns `false` if the color is transparent +// returns `false` if the color is transparent +function setupGLColor (constref clr: TGxRGBA): Boolean; +begin + if (clr.a < 255) then + begin + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + end + else + begin + glDisable(GL_BLEND); + end; + glColor4ub(clr.r, clr.g, clr.b, clr.a); + result := (clr.a <> 0); +end; + +function isScaled (): Boolean; +var + mt: packed array [0..15] of GLfloat; +begin + glGetFloatv(GL_MODELVIEW_MATRIX, @mt[0]); + result := (mt[0] <> 1.0) or (mt[1*4+1] <> 1.0); +end; + // ////////////////////////////////////////////////////////////////////////// // //TODO: OpenGL framebuffers and shaders state @@ -209,7 +259,9 @@ var // ////////////////////////////////////////////////////////////////////////// // // set active context; `ctx` can be `nil` -procedure gxSetContext (ctx: TGxContext; ascale: Single=1.0); +procedure gxSetContextInternal (ctx: TGxContext; ascale: Single; domatrix: Boolean); +var + mt: packed array [0..15] of GLfloat; begin if (savedGLState.saved) then savedGLState.restore(); @@ -224,15 +276,30 @@ begin begin ctx.mActive := true; savedGLState.save(); - oglSetup2D(fuiScrWdt, fuiScrHgt); - glScalef(ascale, ascale, 1.0); - ctx.mScaled := (ascale <> 1.0); - ctx.mScale := ascale; + if (domatrix) then + begin + oglSetup2D(fuiScrWdt, fuiScrHgt); + glScalef(ascale, ascale, 1.0); + ctx.mScaled := (ascale <> 1.0); + ctx.mScale := ascale; + end + else + begin + // assume uniform scale + glGetFloatv(GL_MODELVIEW_MATRIX, @mt[0]); + ctx.mScaled := (mt[0] <> 1.0) or (mt[1*4+1] <> 1.0); + ctx.mScale := mt[0]; + oglSetup2DState(); + end; ctx.onActivate(); end; end; +procedure gxSetContext (ctx: TGxContext; ascale: Single=1.0); begin gxSetContextInternal(ctx, ascale, true); end; +procedure gxSetContextNoMatrix (ctx: TGxContext); begin gxSetContextInternal(ctx, 1, false); end; + + // ////////////////////////////////////////////////////////////////////////// // type TScissorSave = record @@ -285,8 +352,6 @@ end; // ////////////////////////////////////////////////////////////////////////// // -{$INCLUDE fui_gfx_gl_fonts.inc} - type TGxBmpFont = class(TGxFont) private @@ -295,15 +360,20 @@ type mFontBmp: PByte; mFontWdt: PByte; mFreeFontWdt: Boolean; + mFreeFontBmp: Boolean; protected procedure oglCreateTexture (); procedure oglDestroyTexture (); + procedure initDrawText (); + procedure doneDrawText (); + function drawCharInterim (x, y: Integer; const ch: AnsiChar): Integer; // return width (not including last empty pixel) + function drawCharInternal (x, y: Integer; const ch: AnsiChar): Integer; // return width (not including last empty pixel) function drawTextInternal (x, y: Integer; const s: AnsiString): Integer; // return width (not including last empty pixel) public - constructor Create (const aname: AnsiString; awdt, ahgt: Integer; const afont: PByte; const awdtable: PByte=nil); + constructor Create (const aname: AnsiString; st: TStream; proportional: Boolean); destructor Destroy (); override; function charWidth (const ch: AnsiChar): Integer; override; @@ -311,37 +381,77 @@ type end; -constructor TGxBmpFont.Create (const aname: AnsiString; awdt, ahgt: Integer; const afont: PByte; const awdtable: PByte=nil); +constructor TGxBmpFont.Create (const aname: AnsiString; st: TStream; proportional: Boolean); var - c: Integer; + sign: packed array [0..7] of AnsiChar; + enc: packed array [0..16] of AnsiChar; + b: Byte; + wdt, hgt, elen: Integer; + ch, dy: Integer; + fntbwdt: Integer; + wrd: Word; begin - if (afont = nil) then raise Exception.Create('internal error in font creation'); - if (ahgt < 1) then raise Exception.Create('internal error in font creation'); - if (awdt > 0) then + mFreeFontBmp := true; + mFreeFontWdt := true; + mName := aname; + mTexId := 0; + // signature + st.ReadBuffer(sign[0], 8); + if (sign <> 'FUIFONT0') then raise Exception.Create('FlexUI: invalid font file signature'); + // encoding length and width + st.ReadBuffer(b, 1); + wdt := (b and $0f)+1; // 16 is not supported + if (wdt = 16) then raise Exception.Create('FlexUI: 16-wdt fonts aren''t supported yet'); + elen := ((b shr 4) and $0f); + if (elen = 0) then raise Exception.CreateFmt('FlexUI: invalid font encoding length: %d', [elen]); + // height + st.ReadBuffer(b, 1); + hgt := b; + if (hgt < 2) then raise Exception.CreateFmt('FlexUI: invalid font height: %d', [hgt]); + // encoding + st.ReadBuffer(enc[0], elen); + // check for 'cp1251' here (it can also be 'koi8') + if (wdt <= 8) then fntbwdt := 1 else fntbwdt := 2; + // shift and width table (hi nibble: left shift for proportional print; lo nibble: shifted character width for proportional print) + GetMem(mFontWdt, 256); + st.ReadBuffer(mFontWdt^, 256); + // font bitmap + GetMem(mFontBmp, (hgt*fntbwdt)*256); + st.ReadBuffer(mFontBmp^, (hgt*fntbwdt)*256); + mWidth := wdt; + mHeight := hgt; + mBaseLine := hgt-1; //FIXME + if (proportional) then begin - //if (awdtable <> nil) then raise Exception.Create('internal error in font creation'); - mFreeFontWdt := true; - // create width table - GetMem(mFontWdt, 256); - for c := 0 to 255 do mFontWdt[c] := awdt-1; + // shift font + for ch := 0 to 255 do + begin + for dy := 0 to hgt-1 do + begin + if (fntbwdt = 1) then + begin + mFontBmp[ch*hgt+dy] := mFontBmp[ch*hgt+dy] shl (mFontWdt[ch] shr 4); + end + else + begin + wrd := mFontBmp[ch*(hgt*2)+(dy*2)]+256*mFontBmp[ch*(hgt*2)+(dy*2)+1]; + wrd := wrd shl (mFontWdt[ch] shr 4); + mFontBmp[ch*(hgt*2)+(dy*2)+0] := (wrd and $ff); + mFontBmp[ch*(hgt*2)+(dy*2)+1] := ((wrd shr 16) and $ff); + end; + end; + end; end else begin - if (awdtable = nil) then raise Exception.Create('internal error in font creation'); - awdt := 0; - mFontWdt := awdtable; + FillChar(mFontWdt^, 256, wdt); end; - mName := aname; - mWidth := awdt; - mHeight := ahgt; - mBaseLine := ahgt-1; //FIXME - mFontBmp := afont; - mTexId := 0; end; destructor TGxBmpFont.Destroy (); begin + if (mFreeFontBmp) and (mFontBmp <> nil) then FreeMem(mFontBmp); if (mFreeFontWdt) and (mFontWdt <> nil) then FreeMem(mFontWdt); mName := ''; mWidth := 0; @@ -350,14 +460,91 @@ begin mFontBmp := nil; mFontWdt := nil; mFreeFontWdt := false; + mFreeFontBmp := false; mTexId := 0; inherited; end; procedure TGxBmpFont.oglCreateTexture (); +const + TxWidth = 16*16; + TxHeight = 16*16; +var + tex, tpp: PByte; + b: Byte; + cc: Integer; + x, y, dx, dy: Integer; begin - mTexId := createFontTexture(mFontBmp, mFontWdt, (mWidth <= 0)); + GetMem(tex, TxWidth*TxHeight*4); + FillChar(tex^, TxWidth*TxHeight*4, 0); + + for cc := 0 to 255 do + begin + x := (cc mod 16)*16; + y := (cc div 16)*16; + for dy := 0 to mHeight-1 do + begin + if (mWidth <= 8) then b := mFontBmp[cc*mHeight+dy] else b := mFontBmp[cc*(mHeight*2)+(dy*2)+1]; + //if prop then b := b shl (fontwdt[cc] shr 4); + tpp := tex+((y+dy)*(TxWidth*4))+x*4; + for dx := 0 to 7 do + begin + if ((b and $80) <> 0) then + begin + tpp^ := 255; Inc(tpp); + tpp^ := 255; Inc(tpp); + tpp^ := 255; Inc(tpp); + tpp^ := 255; Inc(tpp); + end + else + begin + tpp^ := 0; Inc(tpp); + tpp^ := 0; Inc(tpp); + tpp^ := 0; Inc(tpp); + tpp^ := 0; Inc(tpp); + end; + b := (b and $7f) shl 1; + end; + if (mWidth > 8) then + begin + b := mFontBmp[cc*(mHeight*2)+(dy*2)+0]; + for dx := 0 to 7 do + begin + if ((b and $80) <> 0) then + begin + tpp^ := 255; Inc(tpp); + tpp^ := 255; Inc(tpp); + tpp^ := 255; Inc(tpp); + tpp^ := 255; Inc(tpp); + end + else + begin + tpp^ := 0; Inc(tpp); + tpp^ := 0; Inc(tpp); + tpp^ := 0; Inc(tpp); + tpp^ := 0; Inc(tpp); + end; + b := (b and $7f) shl 1; + end; + end; + end; + end; + + glGenTextures(1, @mTexId); + if (mTexId = 0) then raise Exception.Create('can''t create FlexUI font texture'); + + glBindTexture(GL_TEXTURE_2D, mTexId); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TxWidth, TxHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex); + glFinish(); + + glBindTexture(GL_TEXTURE_2D, 0); + FreeMem(tex); end; @@ -393,45 +580,69 @@ begin end; -// return width (not including last empty pixel) -function TGxBmpFont.drawTextInternal (x, y: Integer; const s: AnsiString): Integer; -var - ch: AnsiChar; - tx, ty: Integer; +procedure TGxBmpFont.initDrawText (); begin - if (Length(s) = 0) then begin result := 0; exit; end; - - result := -1; - glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_NOTEQUAL, 0.0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mTexId); +end; - for ch in s do - begin - tx := (Integer(ch) mod 16)*8; - ty := (Integer(ch) div 16)*8; - glBegin(GL_QUADS); - glTexCoord2f((tx+0)/128.0, (ty+0)/128.0); glVertex2i(x+0, y+0); // top-left - glTexCoord2f((tx+8)/128.0, (ty+0)/128.0); glVertex2i(x+8, y+0); // top-right - glTexCoord2f((tx+8)/128.0, (ty+8)/128.0); glVertex2i(x+8, y+8); // bottom-right - glTexCoord2f((tx+0)/128.0, (ty+8)/128.0); glVertex2i(x+0, y+8); // bottom-left - glEnd(); - x += (mFontWdt[Byte(ch)] and $0f)+1; - result += (mFontWdt[Byte(ch)] and $0f)+1; - end; +procedure TGxBmpFont.doneDrawText (); +begin glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); end; +function TGxBmpFont.drawCharInterim (x, y: Integer; const ch: AnsiChar): Integer; +var + tx, ty: Integer; +begin + tx := (Integer(ch) mod 16)*16; + ty := (Integer(ch) div 16)*16; + glBegin(GL_QUADS); + glTexCoord2f((tx+0)/256.0, (ty+0)/256.0); glVertex2i(x+0, y+0); // top-left + glTexCoord2f((tx+mWidth)/256.0, (ty+0)/256.0); glVertex2i(x+mWidth, y+0); // top-right + glTexCoord2f((tx+mWidth)/256.0, (ty+mHeight)/256.0); glVertex2i(x+mWidth, y+mHeight); // bottom-right + glTexCoord2f((tx+0)/256.0, (ty+mHeight)/256.0); glVertex2i(x+0, y+mHeight); // bottom-left + glEnd(); + result := (mFontWdt[Byte(ch)] and $0f); +end; + + +function TGxBmpFont.drawCharInternal (x, y: Integer; const ch: AnsiChar): Integer; +begin + initDrawText(); + result := drawCharInterim(x, y, ch); + doneDrawText(); +end; + + +function TGxBmpFont.drawTextInternal (x, y: Integer; const s: AnsiString): Integer; +var + ch: AnsiChar; + wdt: Integer; +begin + if (Length(s) = 0) then begin result := 0; exit; end; + result := -1; + initDrawText(); + for ch in s do + begin + wdt := drawCharInterim(x, y, ch)+1; + x += wdt; + result += wdt; + end; + doneDrawText(); +end; + + // ////////////////////////////////////////////////////////////////////////// // var fontList: array of TGxBmpFont = nil; - defaultFontName: AnsiString = 'dos'; + defaultFontName: AnsiString = 'win14'; function strEquCI (const s0, s1: AnsiString): Boolean; @@ -472,6 +683,7 @@ begin end; +{ procedure deleteFonts (); var f: Integer; @@ -479,16 +691,55 @@ begin for f := 0 to High(fontList) do freeAndNil(fontList[f]); fontList := nil; end; +} -procedure createFonts (); +procedure fuiGfxLoadFont (const fontname: AnsiString; const fontFile: AnsiString; proportional: Boolean=false); +var + st: TStream; begin - deleteFonts(); - SetLength(fontList, 4); - fontList[0] := TGxBmpFont.Create('dos', 8, 8, @kgiFont8[0], @kgiFont8PropWidth[0]); - fontList[1] := TGxBmpFont.Create('dos-prop', 0, 8, @kgiFont8[0], @kgiFont8PropWidth[0]); - fontList[2] := TGxBmpFont.Create('msx', 6, 8, @kgiFont6[0], @kgiFont6PropWidth[0]); - fontList[3] := TGxBmpFont.Create('msx-prop', 0, 8, @kgiFont6[0], @kgiFont6PropWidth[0]); + if (Length(fontname) = 0) then raise Exception.Create('FlexUI: cannot load nameless font '''+fontFile+''''); + st := fuiOpenFile(fontFile); + if (st = nil) then raise Exception.Create('FlexUI: cannot load font '''+fontFile+''''); + try + fuiGfxLoadFont(fontname, st, proportional); + except on e: Exception do + begin + writeln('FlexUI font loadin error: ', e.message); + FreeAndNil(st); + raise Exception.Create('FlexUI: cannot load font '''+fontFile+''''); + end; + else + raise; + end; + FreeAndNil(st); +end; + + +procedure fuiGfxLoadFont (const fontname: AnsiString; st: TStream; proportional: Boolean=false); +var + fnt: TGxBmpFont = nil; + f: Integer; +begin + if (Length(fontname) = 0) then raise Exception.Create('FlexUI: cannot load nameless font'); + fnt := TGxBmpFont.Create(fontname, st, proportional); + try + for f := 0 to High(fontList) do + begin + if (strEquCI(fontList[f].name, fontname)) then + begin + if (fontList[f].mTexId <> 0) then raise Exception.Create('FlexUI: cannot reload generated font named '''+fontname+''''); + FreeAndNil(fontList[f]); + fontList[f] := fnt; + exit; + end; + end; + SetLength(fontList, Length(fontList)+1); + fontList[High(fontList)] := fnt; + except + FreeAndNil(fnt); + raise; + end; end; @@ -509,10 +760,8 @@ end; // ////////////////////////////////////////////////////////////////////////// // -procedure oglSetup2D (winWidth, winHeight: Integer; upsideDown: Boolean=false); +procedure oglSetup2DState (); begin - glViewport(0, 0, winWidth, winHeight); - glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_LINE_SMOOTH); @@ -527,6 +776,17 @@ begin glDisable(GL_CULL_FACE); glDisable(GL_ALPHA_TEST); + glClearColor(0, 0, 0, 0); + glColor4f(1, 1, 1, 1); +end; + + +procedure oglSetup2D (winWidth, winHeight: Integer; upsideDown: Boolean=false); +begin + glViewport(0, 0, winWidth, winHeight); + + oglSetup2DState(); + glMatrixMode(GL_TEXTURE); glLoadIdentity(); @@ -546,9 +806,6 @@ begin glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - - glClearColor(0, 0, 0, 0); - glColor4f(1, 1, 1, 1); end; @@ -558,33 +815,6 @@ end; procedure oglDrawCursor (); begin oglDrawCursorAt(fuiMouseX, fuiMouseY); end; -// ////////////////////////////////////////////////////////////////////////// // -// returns `false` if the color is transparent -// returns `false` if the color is transparent -function setupGLColor (constref clr: TGxRGBA): Boolean; -begin - if (clr.a < 255) then - begin - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - end - else - begin - glDisable(GL_BLEND); - end; - glColor4ub(clr.r, clr.g, clr.b, clr.a); - result := (clr.a <> 0); -end; - -function mScaled (): Boolean; -var - mt: packed array [0..15] of Double; -begin - glGetDoublev(GL_MODELVIEW_MATRIX, @mt[0]); - result := (mt[0] <> 1.0) or (mt[1*4+1] <> 1.0); -end; - - // ////////////////////////////////////////////////////////////////////////// // constructor TGxContext.Create (); begin @@ -768,7 +998,7 @@ begin glVertex2f(x+len+0.375, y+0.375); glEnd(); end - else + else if (mScale > 1.0) then begin glBegin(GL_QUADS); glVertex2i(x, y); @@ -776,6 +1006,13 @@ begin glVertex2i(x+len, y+1); glVertex2i(x, y+1); glEnd(); + end + else + begin + glPointSize(1); + glBegin(GL_POINTS); + while (len > 0) do begin glVertex2i(x, y); Inc(x); Dec(len); end; + glEnd(); end; end; @@ -792,7 +1029,7 @@ begin glVertex2f(x+0.375, y+len+0.375); glEnd(); end - else + else if (mScale > 1.0) then begin glBegin(GL_QUADS); glVertex2i(x, y); @@ -800,33 +1037,18 @@ begin glVertex2i(x+1, y+len); glVertex2i(x+1, y); glEnd(); - end; -end; - - -procedure TGxContext.rect (x, y, w, h: Integer); - procedure hlinex (x, y, len: Integer); + end + else begin - if (len < 1) then exit; - glBegin(GL_QUADS); - glVertex2i(x, y); - glVertex2i(x+len, y); - glVertex2i(x+len, y+1); - glVertex2i(x, y+1); + glPointSize(1); + glBegin(GL_POINTS); + while (len > 0) do begin glVertex2i(x, y); Inc(y); Dec(len); end; glEnd(); end; +end; - procedure vlinex (x, y, len: Integer); - begin - if (len < 1) then exit; - glBegin(GL_QUADS); - glVertex2i(x, y); - glVertex2i(x, y+len); - glVertex2i(x+1, y+len); - glVertex2i(x+1, y); - glEnd(); - end; +procedure TGxContext.rect (x, y, w, h: Integer); begin if (not mActive) or (mClipRect.w < 1) or (mClipRect.h < 1) or (mColor.a = 0) then exit; if (w < 0) or (h < 0) then exit; @@ -851,10 +1073,10 @@ begin end else begin - hlinex(x, y, w); - hlinex(x, y+h-1, w); - vlinex(x, y+1, h-2); - vlinex(x+w-1, y+1, h-2); + hline(x, y, w); + hline(x, y+h-1, w); + vline(x, y+1, h-2); + vline(x+w-1, y+1, h-2); end; end; end; @@ -917,7 +1139,7 @@ function TGxContext.drawChar (x, y: Integer; const ch: AnsiChar): Integer; // re begin result := mFont.charWidth(ch); if (not mActive) or (mClipRect.w < 1) or (mClipRect.h < 1) or (mColor.a = 0) then exit; - TGxBmpFont(mFont).drawTextInternal(x, y, ch); + TGxBmpFont(mFont).drawCharInternal(x, y, ch); end; function TGxContext.drawText (x, y: Integer; const s: AnsiString): Integer; // returns text width @@ -928,14 +1150,57 @@ begin end; -function TGxContext.iconMarkWidth (ic: TMarkIcon): Integer; begin result := 11; end; -function TGxContext.iconMarkHeight (ic: TMarkIcon): Integer; begin result := 8; end; +function TGxContext.iconMarkWidth (ic: TMarkIcon): Integer; +begin + {$IFDEF FUI_TEXT_ICONS} + case ic of + TMarkIcon.Checkbox: result := textWidth('[x]'); + TMarkIcon.Radiobox: result := textWidth('(*)'); + else result := textWidth('[x]'); + end; + {$ELSE} + result := 11; + {$ENDIF} +end; + +function TGxContext.iconMarkHeight (ic: TMarkIcon): Integer; +begin + {$IFDEF FUI_TEXT_ICONS} + case ic of + TMarkIcon.Checkbox: result := textHeight('[x]'); + TMarkIcon.Radiobox: result := textHeight('(*)'); + else result := textHeight('[x]'); + end; + {$ELSE} + result := 8; + {$ENDIF} +end; procedure TGxContext.drawIconMark (ic: TMarkIcon; x, y: Integer; marked: Boolean); var + {$IFDEF FUI_TEXT_ICONS} + xstr: AnsiString; + {$ELSE} f: Integer; + {$ENDIF} begin if (not mActive) or (mClipRect.w < 1) or (mClipRect.h < 1) or (mColor.a = 0) then exit; + {$IFDEF FUI_TEXT_ICONS} + case ic of + TMarkIcon.Checkbox: xstr := '[x]'; + TMarkIcon.Radiobox: xstr := '(*)'; + else exit; + end; + if (marked) then + begin + drawText(x, y, xstr); + end + else + begin + drawChar(x, y, xstr[1]); + drawChar(x+textWidth(xstr)-charWidth(xstr[3]), y, xstr[3]); + end; + {$ELSE} if (ic = TMarkIcon.Checkbox) then begin vline(x, y, 7); @@ -973,26 +1238,143 @@ begin hline(x+4, y+5, 3); end; end; + {$ENDIF} end; -function TGxContext.iconWinWidth (ic: TWinIcon): Integer; begin result := 9; end; -function TGxContext.iconWinHeight (ic: TWinIcon): Integer; begin result := 8; end; +function TGxContext.iconWinWidth (ic: TWinIcon): Integer; +begin + {$IFDEF FUI_TEXT_ICONS} + case ic of + TWinIcon.Close: result := nmax(textWidth('[x]'), textWidth('[#]')); + else result := nmax(textWidth('[x]'), textWidth('[#]')); + end; + {$ELSE} + result := 9; + {$ENDIF} +end; + +function TGxContext.iconWinHeight (ic: TWinIcon): Integer; +begin + {$IFDEF FUI_TEXT_ICONS} + case ic of + TWinIcon.Close: result := nmax(textHeight('[x]'), textHeight('[#]')); + else result := nmax(textHeight('[x]'), textHeight('[#]')); + end; + {$ELSE} + result := 8; + {$ENDIF} +end; procedure TGxContext.drawIconWin (ic: TWinIcon; x, y: Integer; pressed: Boolean); var + {$IFDEF FUI_TEXT_ICONS} + xstr: AnsiString; + wdt: Integer; + {$ELSE} f: Integer; + {$ENDIF} begin if (not mActive) or (mClipRect.w < 1) or (mClipRect.h < 1) or (mColor.a = 0) then exit; + {$IFDEF FUI_TEXT_ICONS} + case ic of + TWinIcon.Close: if (pressed) then xstr := '[#]' else xstr := '[x]'; + else exit; + end; + wdt := nmax(textWidth('[x]'), textWidth('[#]')); + drawChar(x, y, xstr[1]); + drawChar(x+wdt-charWidth(xstr[3]), y, xstr[3]); + drawChar(x+((wdt-charWidth(xstr[2])) div 2), y, xstr[2]); + {$ELSE} if pressed then rect(x, y, 9, 8); for f := 1 to 5 do begin vline(x+1+f, y+f, 1); vline(x+1+6-f, y+f, 1); end; + {$ENDIF} end; +procedure TGxContext.glSetScale (ascale: Single); +begin + if (ascale < 0.01) then ascale := 0.01; + glLoadIdentity(); + glScalef(ascale, ascale, 1.0); + mScale := ascale; + mScaled := (ascale <> 1.0); +end; + +procedure TGxContext.glSetTrans (ax, ay: Single); +begin + glLoadIdentity(); + glScalef(mScale, mScale, 1.0); + glTranslatef(ax, ay, 0); +end; + + +procedure TGxContext.glSetScaleTrans (ascale, ax, ay: Single); +begin + glSetScale(ascale); + glTranslatef(ax, ay, 0); +end; + + +// vertical scroll bar +procedure TGxContext.drawVSBar (x, y, wdt, hgt: Integer; cur, min, max: Integer; constref clrfull, clrempty: TGxRGBA); +var + filled: Integer; +begin + if (wdt < 1) or (hgt < 1) then exit; + filled := sbarFilled(hgt, cur, min, max); + color := clrfull; + fillRect(x, y, wdt, filled); + color := clrempty; + fillRect(x, y+filled, wdt, hgt-filled); +end; + + +// horizontal scrollbar +procedure TGxContext.drawHSBar (x, y, wdt, hgt: Integer; cur, min, max: Integer; constref clrfull, clrempty: TGxRGBA); +var + filled: Integer; +begin + if (wdt < 1) or (hgt < 1) then exit; + filled := sbarFilled(wdt, cur, min, max); + color := clrfull; + fillRect(x, y, filled, hgt); + color := clrempty; + fillRect(x+filled, y, wdt-filled, hgt); +end; + + +class function TGxContext.sbarFilled (wh: Integer; cur, min, max: Integer): Integer; +begin + if (wh < 1) then result := 0 + else if (min > max) then result := 0 + else if (min = max) then result := wh + else + begin + if (cur < min) then cur := min else if (cur > max) then cur := max; + result := wh*(cur-min) div (max-min); + end; +end; + + +class function TGxContext.sbarPos (cxy: Integer; xy, wh: Integer; min, max: Integer): Integer; +begin + if (wh < 1) then begin result := 0; exit; end; + if (min > max) then begin result := 0; exit; end; + if (min = max) then begin result := max; exit; end; + if (cxy < xy) then begin result := min; exit; end; + if (cxy >= xy+wh) then begin result := max; exit; end; + result := min+((max-min)*(cxy-xy) div wh); + assert((result >= min) and (result <= max)); +end; + + + + // ////////////////////////////////////////////////////////////////////////// // (* procedure oglRestoreMode (doClear: Boolean); @@ -1028,8 +1410,8 @@ end; *) -//procedure onWinFocus (); begin end; -//procedure onWinBlur (); begin fuiResetKMState(true); end; +//procedure onWinFocus (); begin uiFocus(); end; +//procedure onWinBlur (); begin fuiResetKMState(true); uiBlur(); end; //procedure onPreRender (); begin oglRestoreMode(gGfxDoClear); end; procedure onPostRender (); begin oglDrawCursor(); end; @@ -1057,7 +1439,7 @@ end; // ////////////////////////////////////////////////////////////////////////// // initialization savedGLState := TSavedGLState.Create(false); - createFonts(); + //createFonts(); //winFocusCB := onWinFocus; //winBlurCB := onWinBlur; //prerenderFrameCB := onPreRender;